home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ada1804.zip / ADA1804.HLP < prev   
Text File  |  1990-09-21  |  123KB  |  3,488 lines

  1.  
  2.  
  3.                                    DRAFT
  4.  
  5.  
  6.                           ADA STYLE GUIDE HANDBOOK
  7.  
  8.                               MIL-HDBK-1804
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.                           TABLE OF CONTENTS
  16.  
  17. 1.0     SCOPE
  18. 1.1     Introduction
  19. 1.2     Scope
  20. 1.3     Goals
  21.  
  22. 2.0     REFERENCED DOCUMENTS
  23. 2.1     Usage
  24. 2.2     Referenced Documents
  25.  
  26. 3.0     DEFINITIONS
  27. 3.1     Introduction
  28. 3.2     Handbook
  29. 3.3     Standard
  30.  
  31. 4.0     GENERAL REQUIREMENTS
  32.  
  33. 5.0     SPECIFIC GUIDELINES
  34. 5.1     Introduction
  35. 5.2     Lexical Elements
  36. 5.3     Declarations and Types
  37. 5.4     Names and Expressions
  38. 5.5     Statements
  39. 5.6     Subprograms
  40. 5.7     Packages
  41. 5.8     Visibility
  42. 5.9     Tasks
  43. 5.10    Program Structure and Compilation Issues
  44. 5.11    Exceptions
  45. 5.12    Generic Units
  46. 5.13    Representation Clauses and Implementation-Dependent Features
  47. 5.14    Input-Output
  48.  
  49.  
  50.  
  51.                                    1.  SCOPE.
  52.  
  53.  
  54. 1.1  Introduction.  Ada is a programming language of considerable expressive
  55. power.  ANSI/MIL-STD-1815A, Ada Programming Language, provides a thorough
  56. definition of the language.  However, it does not offer sufficient guidance on
  57. the appropriate use of Ada's powerful features.  This document was developed
  58. to address "program style" issues and is presented as if the reader does not
  59. have a mentor to explain all the whys and wherefores.  It is for this reason
  60. the document goes beyond styling techniques in some sections by showing
  61. what is "good and proper" Ada constructs, denoting what to avoid, or why
  62. certain constructs are used in a particular manner (proper software
  63. engineering techniques are also "good style").  Besides, both facets are
  64. needed in the code produced for the next person in line - the maintainer
  65. and/or reuser.
  66.  
  67. 1.2  Scope.  Program source code serves two functions:  to specify an
  68. algorithm to be performed on a computer, and to communicate this algorithmic
  69. design to other human readers.  Program style relates to how well a program
  70. meets the second function.  It is a consistent manner of using the features of
  71. a programming language to promote the maintainability, readability and
  72. understandability of a program.  This is a matter of the form of the final,
  73. delivered, program source code, as opposed to the process of developing the
  74. code.
  75.  
  76. 1.3  Goals.
  77.  
  78.      a.  While some of what constitutes "good style" is subjective and
  79. somewhat arbitrary, it is important that the style of a program be consistent
  80. throughout the program.  The primary goal of this guide is to promote such
  81. consistent use of good style across large numbers of Ada programs.  The whole
  82. intent of "good style" is to increase the readability of these programs.
  83. Therefore, these guidelines follow from general principles of program
  84. readability and understandability.
  85.  
  86.      b.  The program should reflect the natural levels of abstraction in the
  87. problem domain, so that the reader can reasonably comprehend each level
  88. individually.  Just as entites in real world applications have structure and
  89. organization, so should Ada software systems.  Furthermore, on a gobal level,
  90. the overall software architecture should exhibit clarity and be readilly
  91. comprehended.  Ada coding style plays an important role in attainment of
  92. these goals.
  93.  
  94.      c.  There are several features in Ada which are unfamiliar to many
  95. programmers.  There is thus a tendency to either underuse these features or to
  96. use them inappropriately.  A feature of Ada should generally not be ignored,
  97. but neither should it be used in excess.  The guidelines highlight the proper
  98. use of Ada features.  Keep in mind, there are features in the Ada language
  99. that when used, are considered poor programming and/or software engineering
  100. practices.  Most of this knowledge has become apparent through the use of the
  101. language.  This guide's intent is to alert the reader of these practices; and
  102. although they are functionally correct, should be avoided.  (Words to that
  103. effect will be used).
  104.  
  105.      d.  The textual format of a program should be pleasing to the eye and
  106. promote the readability and understandability of the program.  The format
  107. should highlight the structure of a program and the role of a program as a
  108. model of the problem domain.  Just as the careful layout of a book can enhance
  109. written communication, the careful layout of a program can enhance the
  110. communication of algorithmic design to another human.  The consistent use of
  111. formatting style is especially important, because it allows readers to become
  112. accustomed to the familiar layout of the program constructs.  An automated
  113. formatting program is particularly helpful, but even in the absence of such a
  114. tool, much can be gained from a common format style.
  115.  
  116.                           2. REFERENCED DOCUMENTS
  117.  
  118.  
  119. 2.1  Usage.
  120.  
  121.      a.  This is not a static document.  Other references need to be consulted
  122. to provide a valid mix of ideas and "legal" practices when coding Ada.  Where
  123. applicable, conformity among the references should be obtained.  Instances,
  124. for example, where adopting an ISO or ARTEWG practice does not have a negative
  125. impact, should be encouraged.
  126.  
  127.      b.  A listing of other references beside the one given in paragraph 2.2
  128. will not be made.  Other documents were referenced; however, to list them
  129. could be construed as an endorsement of the document to the exclusion of
  130. others.  Better none than to miss one.
  131.  
  132. 2.2  Reference documents.  ANSI/MIL-STD-1815A, Ada Programming Language.
  133.  
  134.                                 3.  DEFINITIONS
  135.  
  136.  
  137. 3.1  Introduction.  The definitions and acronyms provided in Ada Reference
  138. Manual - ANSI/MIL-STD-1815A are applicable for use with this handbook.  Since
  139. this handbook is intended to be a companion document to the Ada Programming
  140. Language manual, the definitions and acronyms are not restated here.
  141.  
  142. 3.2  Handbook.  The term "Handbook" (capitalization intended) refers to this
  143. document, MIL-HDBK-1804, Ada Style Guide Handbook.  This simplification is
  144. used to improve readability.
  145.  
  146. 3.3  Standard.  The term "Standard" (capitalization intended) refers to
  147. ANSI/MIL-STD-1815A, Ada Programming Language.  This simplification is to
  148. improve readability.
  149.  
  150.                            4. GENERAL REQUIREMENTS
  151.  
  152.                                 NOT APPLICABLE
  153.  
  154.                            5.  SPECIFIC GUIDELINES
  155.  
  156.  
  157. 5.1  Introduction.  This section contains fourteen major subparagraphs (5.1
  158. through 5.14) corresponding to the fourteen chapters of ANSI/MIL-STD-1815A,
  159. Ada Programming Language.  This provides a standard frame of reference for the
  160. discussion of Ada features.  Where appropriate, the guide includes examples
  161. and justifications for various guidelines.  Some of the major subparagraphs,
  162. themselves, have an "Examples" subparagraph giving additional, longer examples
  163. for the topic.  When more than one example is shown, the order of preference
  164. will be with the first example, then the second, etc.
  165.  
  166. 5.1.1  Correlation.  Each major subparagraph bears the same title as its
  167. corresponding chapter in the Standard, e.g.  Lexical elements is chapter 5.2
  168. in this style guide.  In the Standard, the basic definition starts in chapter
  169. 2.
  170.  
  171. 5.1.2  Handbook Format.
  172.  
  173.      a.  Some constraints are implicity included in this Handbook.  The reason
  174. - the explanations are directed towards the Management Information Systems
  175. environment moreso than the real-time, embedded systems environment.  (Granted,
  176. Ada was initially intended for the latter).  Problems in "style" may occur
  177. when information presented is slanted towards large memory features instead of
  178. constrained, limited memory systems.  (Block statements come to mind as an
  179. example).  Therefore, for real-time programmers/maintainers, comments starting
  180. with "REAL_TIME" will be included and are directed to their use.
  181.  
  182.      b.  Non-numbered paragraphs are editorial comments included to provide
  183. further clarifications.  Also, information in this category and begun with
  184. the notation of "NOTE:", are of specific interest and special attention should
  185. be paid to them.
  186.  
  187. 5.1.3   Non-compliance.   It should be noted that some compilers contain
  188. restrictions that may not allow compliance with all of the guidelines contained
  189. in Section 5.2 and beyond.  An example would be the inability of a system to
  190. allow the use of the underscore.  The Standard, chapter 2.1, "Charater Set",
  191. includes the underscore as an allowable special character.  Obviously, a
  192. physical impasse is apparent, and as such, should be documented up front in
  193. the program.  This is a basic premise of this guide - if you cannot comply
  194. with the guidance, information stating such should appear in the program.
  195.  
  196. 5.1.4   Basic Style Format.
  197.  
  198.       a.  The emphasis in style is to have distinct, recognizable parts.  That
  199. is, information to be defined should be on one side, information doing the
  200. defining on the other; or, on one line, with the defining components on the
  201. following line(s).  The right-left concept comes more into play with the usage
  202. of the assignment operator (see 5.2.2.7).  The one-line-next-line concept will
  203. cover the majority of style formating use.
  204.  
  205.       b.  The reasons for promoting the one-line-next-line style are reada-
  206. bility and understandability.  From the first character on a line to its
  207. associated semicolon, some information contained between the two must be
  208. dominant, some must be subordinate.  Whether all the information is on one
  209. line or many does not matter syntactically, it does for readability and
  210. understandability.  Therefore, to promote easier end of line comments,
  211. maintainability, as well as readability and understandability, the following
  212. basic style is recommended (exceptions are delineated in other chapter 5
  213. subchapters):
  214.  
  215.       1)  Reserved words denoting various elements of an Ada program and
  216. their associated names should be on one line, their subordinate information
  217. on the succeeding line(s), e.g.
  218.  
  219.           procedure <procedure name>
  220.             [<parameter specification>];
  221.  
  222.           function <function name>
  223.             [<parameter specification>];
  224.  
  225.       2)  Type declarations or other reserve word phrases ending with a verb
  226. should be on one line, its subordinate information on the succeeding line(s),
  227. e.g.
  228.           type (identifier> is
  229.             <type definition>;
  230.  
  231.           task type <task name> is
  232.             <entry statement>;
  233.           end <task name>;
  234.  
  235.           task body <body name> is separate;
  236.  
  237.           <loop name>:
  238.           while <expression> loop
  239.             <statement>
  240.           end loop <loop name>;
  241.  
  242.      3)  Objects, strings and similar declarations where the colon
  243. differentiates the identifier from the definition, should be "muliti-lined"
  244. by placing the identifier on one line and the colon and the definition on
  245. the subsequent line(s), e.g.
  246.  
  247.           <object name>
  248.             : <definition>;
  249.  
  250.      4)  Information being protrayed using the assignment operator should
  251. use the left-right concept, e.g.
  252.  
  253.           identifier := <expression> [<operator starting continued expression>
  254.                         <continued expression>];
  255.  
  256. The expression(s) are continued by leaving an operator on the previous line
  257. and continuing the expression directly under the start of the expression on
  258. the line above (see 5.2.2.7 for an example).
  259.  
  260.      5)  The basic formats are not used if multiple occurrences of the same
  261. form are used in a subordinate role (see 5.3.8.4 b), e.g.
  262.  
  263.           package <package name> is
  264.             procedure <procedure name> [<passing parameters>];
  265.             procedure <procedure name> [<passing parameters>];
  266.             function  <function name>  [<passing parameters>];
  267.             function  <function name>  [<passing parameters>];
  268.           private
  269.           end <package name>;
  270.  
  271. NOTE:  if any of the procedures or functions in the above example require
  272. continuation to the next line, all of the subordinate information should be
  273. continued in the same manner (see 5.2.2.7).
  274.  
  275. 5.2  Lexical elements.
  276.  
  277.  
  278. 5.2.1  The package STANDARD.  Language words with predefined meanings in the
  279. package STANDARD should not be redefined.
  280.  
  281. 5.2.2  Formatting of lexical elements.
  282.  
  283. 5.2.2.1  Indentation.  The preferred indentation level is two spaces.
  284. Exceptions are in some cases continuations.
  285.  
  286. NOTE:  The emphasis is more on the indention being consistent throughout the
  287. program than the exact number of spaces.  The key word is consistent!
  288.  
  289. 5.2.2.2  Character set.  Full use should be made of the ISO character set
  290. where available.  Alternate character replacements should only be used when
  291. the corresponding graphical symbols are not available or are reserved for
  292. other uses (see chapter 2.10, the Standard).
  293.  
  294. 5.2.2.3  Upper/lower case.
  295.  
  296. NOTE:  This area is one of just a few that cause the most consternation among
  297. Ada coders because rationale can be provided for numerous formating methods.
  298. All things considered, the following was thought best ...
  299.  
  300.     a.  Reserved words and attributes should appear in lower case, e.g.
  301.  
  302.           package body Choice is separate;
  303.  
  304.           type REAL is digits 8;
  305.  
  306.     b.  All identifiers except type, enumeration value and attribute
  307. identifiers should be in mixed upper and lower case.  The first letter of each
  308.  
  309. word in the identifier should be in upper case with other characters in lower
  310. case, unless a word is normally written in all upper case, as are acronyms.
  311.  
  312.     Display_Device
  313.     Number_Of_User Names
  314.     Get_FHST_Data
  315.     Package_Name
  316.     List'first   -- "first" is an attribute designator (preceeded by an
  317.                  -- apostrophe), not a reserve word.
  318.  
  319.     c.  Type names, subtype names and enumeration literals should appear in
  320. all upper case.
  321.  
  322.  
  323.     type COLOR        is (WHITE, RED, YELLOW, GREEN, BLUE, BROWN, BLACK);
  324.       subtype RAINBOW is COLOR range RED .. BLUE;
  325.  
  326.     type ARMED_FORCE is (ARMY, AIR_FORCE, NAVY, MARINES);
  327.  
  328. 5.2.2.4  Identifiers.
  329.  
  330.     a.  Identifier names should be meaningful and easily distinguishable from
  331. each other, including loop parameters, array indices, and common mathematical
  332. variables.  Names of objects and types should be nouns or noun phrases; names
  333. of procedures should be verbs or verb phrases; and, names of enumeration
  334. literals should be adjectives if they are meant to represent properties.
  335.  
  336.     b.  Distinct words in identifiers should always be separated by
  337. underscores.
  338.  
  339.     c.  The use of abbreviations in identifiers should be avoided.  When used,
  340.  
  341. an abbreviation should be significantly shorter than the word it abbreviates,
  342. and its meaning should be clear.  The same abbreviations should be used
  343. consistently throughout a project, precedence is given to sanctioned
  344. standard data elements and codes or existing functional data dictionaries
  345. abbreviations, e.g. MGT for management; RQD for required.
  346.  
  347.     d.  Acronyms should be avoided if at all possible.
  348.  
  349. 5.2.2.5  Spaces.  Single spaces should be used consistently between lexical
  350. elements to enhance readability.
  351.  
  352. 5.2.2.6  Blank lines.
  353.  
  354.     a.  Blank lines should be used to group logically related lines of text.
  355.  
  356. A careful use of blank lines can greatly enhance readability by making the
  357. logical structure of a sequence of lines more textually obvious.  However,
  358. the overuse of blank lines (e.g., "double spacing") defeats the very purpose
  359. of grouping and can actually reduce readability.  Blank lines should thus
  360. always be used with grouping in mind and not just to increase white space.
  361.  
  362.     b.  A blank line should always preceed and follow a construct whose last
  363. line is not at the same indentation level as its first line.
  364.  
  365.     -- preceeded by a blank line
  366.  
  367.     type COMPLEX is
  368.       record
  369.         Real      :  REAL := 0.0;
  370.         Imaginary :  REAL := 0.0;
  371.       end record;
  372.  
  373.    --  Followed by a blank line
  374.  
  375. 5.2.2.7  Continuation of statements.
  376.  
  377.     a. tatements extending over multiple lines should be broken after reserved
  378. words, operators, delimeters, commas, or if a distinct entity can be
  379. separated.  The one-line-next-line concept should be utilized as discussed
  380. in the basic formats section, e.g.
  381.  
  382.            package Information is
  383.              procedure Information_Left_Over
  384.                (Return_File : in RETURN_FILE_TYP);
  385.              function Check_Last_Element
  386.                (Return_File : in RETURN_FILE_TYP)
  387.                  return BOOLEAN;
  388.            end Information;
  389.  
  390. For assignments, use the left-right concept, e.g.
  391.  
  392.     Corrected-Value := ((1 + Sensor_Scale) * Raw_Value) +
  393.                        (Distortion_Factor * Distortion_Value) -
  394.                        Sensor_Bias;
  395.  
  396. NOTE:  Redundant parenthesis are used (see 5.4.2.2).
  397.  
  398.     b.  Long strings extending over more than one line should be broken up at
  399. natural boundaries, appropriate to the meaning of the contents of the string,
  400. if any.
  401.  
  402.     "This is a rather long string, so it is likely that "
  403.       & "it will extend over more than one line"
  404.  
  405. NOTE: Do not confuse continuation with basic format (see 5.1.4).
  406.  
  407. 5.2.2.8  Comments.
  408.  
  409.     a.  Comments should be used to add information for the reader or to high-
  410. light sections of code, and should not merely paraphrase the code.
  411.  
  412.     b.  Comments should begin with the "--" aligned with the indentation level
  413.  
  414. of the code that they describe, or to the right of the code, aligned with
  415. other such comments.
  416.  
  417.     -- Check if the user has special authorization
  418.     if Authority = SPECIAL then
  419.       Display_Special_Menu;    -- All operations are allowed
  420.     else
  421.       Display_Normal_Menu;     -- Only normal operations allowed
  422.     end if;
  423.  
  424.     c.  Refrain from including any character after the "--", even though
  425. the Standard gives an example of numerous hyphens in a row.  Several formal
  426. specification languages (commercial-off-the-shelf tools) use the
  427. --<special symbol> in development and production of automated specification
  428. documents.
  429.  
  430. 5.2.2.9  Length of a Line.  The preferred length of a line is 72 characters.
  431. Various restrictions begin to occur, window boarders, etc., if the line
  432. extends further.
  433.  
  434. 5.3  Declarations and types.
  435.  
  436. NOTE:  Be advised and understand the limitations imposed with predefined
  437. numeric types (FLOAT, INTEGER, etc.) This is due to their implementation
  438. dependent precision.
  439.  
  440. 5.3.1  Constants.
  441.      a.  An object should be declared constant if its value is intended not to
  442. change.
  443.  
  444.  Declaring an object to be constant clearly signals both the human reader and
  445. the compiler the intention that its value will not change.  This not only
  446. increases readability, it also increases reliability because the compiler will
  447. detect any attempt to tamper with the object.  Also, it can result in some
  448. decrease in executable size and better run time efficiency.
  449.  
  450.      b.  Defining a constant object is preferable to using a numeric literal
  451. or expression with constant value, as long as the constant object has an
  452. intrinsic conceptual meaning.  Constants should not be used to avoid
  453. enumeration type.
  454.  
  455. There is no use in defining a constant object when a numeric literal is
  456. obviously more appropriate, for example:  using "One" instead of "1." However,
  457.  
  458. the use of constant objects with intrinsic meaning (such as "Buffer_Size" or
  459. "Field_Of_View") can greatly increase the readability of code.  Further, the
  460. code is more maintainable since a change in a value will be localized to the
  461. constant declaration.
  462.  
  463.      c.  A named number (i.e., a constant object with type universal-integer
  464. or universal-real) should be used only for values that are truly "universal"
  465. and "typeless." Other numeric constants should be declared with an explicit
  466. type.
  467.  
  468. Constants, such as "Pi", and cardinal integers (e.g., a "number of things")
  469. should be named numbers.  Note also that declaring a constant in terms of a
  470. predefined numeric type (INTEGER, FLOAT, etc.) in most cases has no advantage
  471. over a named number since these predefined types provide only range and
  472. accuracy constraints and not additional conceptual meaning.  In fact, since
  473. the range and accuracy of predefined numeric types is implementation-defined,
  474. portability can be increased by using named numbers, in those cases where a
  475. constant of a user-defined type is not more appropriate.
  476.  
  477.      Pi
  478.        : constant := 3.141_592_65;
  479.  
  480.      Number_Of Sensors          -- This is a named number
  481.        : constant := 4;
  482.  
  483.      Main_Sensor_Number
  484.       : constant SENSOR_INDEX := 2;
  485.  
  486. REAL_TIME:  Multiplication or division of a fixed point type by an integer
  487. results in an object of that fixed point type (as opposed to multiplication
  488. of an integer by an fixed point type, which results in an integer).  Using
  489. a constant of universal fixed rather than a specified fixed point type may
  490. force the introduction of an explicit type conversion, possible reducing the
  491. efficiency of the multiplication.
  492.  
  493. 5.3.2  Types and Subtypes.
  494.  
  495. 5.3.2.1  Types.  Separate types should be used for values that belong to
  496. logically independent declarations, and for distinct concepts.
  497.  
  498.     type X_COORDINATE is
  499.       range 1 .. 640;
  500.  
  501.     type Y_COORDINATE is
  502.       range 1 .. 480;
  503.  
  504.     type PIXEL_VALUE is
  505.       range 0 .. 255;
  506.  
  507.     type IMAGE_GRID is
  508.       array (X_COORDINATE, Y_COORDINATE) of PIXEL_VALUE;
  509.  
  510. A data type characterizes a set of values and a set of operations applicable
  511. to objects of the type.  In the above example, each coordinate has a type
  512. because coordinates are independent entities.  Explicitly declaring these
  513. types makes the concepts more obvious to a human reader and also allows the
  514. detection of mistakes such as:
  515.  
  516.     X_Coord : X_COORDINATE := 1;
  517.     Y_Coord : Y_COORDINATE := 1;
  518.     Pixel   : PIXEL_VALUE  := 0;
  519.     Image   : IMAGE_GRID;
  520.  
  521.     Image (Y_Coord, X_Coord) := Pixel;    -- Should be "(X_Coord, Y_Coord)"
  522.  
  523. The drawback of this kind of typing is that the following construct is
  524. illegal:
  525.  
  526.     if X_Coord = Y_Coord then     -- ILLEGAL since X_Coord and Y_Coord
  527.       ...                         --   have different types
  528.  
  529. A type conversion must be used:
  530.  
  531.     if X_Coord = X_COORDINATE (Y_Coord) then
  532.     ...
  533.  
  534. Note that, depending on context (and compiler quality), there may or may not
  535. be some run time penalty associated with type conversion (e.g., testing of
  536. range constraints).
  537.  
  538. 5.3.2.2  Subtypes.  For understandability and maintainability, all types and
  539. subtypes should be grouped together.  This ensures the type being subtyped,
  540. if it is user defined, already exists in the program.  Subtypes should be
  541. used if the problem consists of subsets of the base type, or subsets of the
  542. subsets, e.g.
  543.  
  544.          type NON_NEGATIVE       is              range 0 .. INTEGER'last;
  545.            subtype ORDER_SIZE    is NON_NEGATIVE range 0 .. 1_000_000;
  546.              subtype SMALL_ORDER is ORDER_SIZE   range 0 .. 50;
  547.              subtype BIG_ORDER   is ORDER_SIZE   range 51 .. 1_000_000;
  548.  
  549. 5.3.3  Enumeration types.  An enumeration type should always be used in
  550. preference to an integer type, unless the logical nature of the concept to be
  551. modeled demands the other.
  552.  
  553. For example the type:
  554.  
  555.     type DEVICE_MODE is
  556.       (READ_ONLY, WRITE_ONLY, READ_WRITE);
  557.  
  558. is preferable to encoding DEVICE_MODE as an integer 0, 1 or 2.
  559.  
  560. 5.3.4  "Point" types.
  561.  
  562. 5.3.4.1  Floating point types.
  563.  
  564.     a.  To enhance portability, always specify the range, constraints and
  565. accuracy of a floating point type.
  566.  
  567.     b.  The precision for the predefined floating types (FLOAT, etc.) is
  568. implementation-dependent, though all implementations should provide at least 6
  569. decimal digits of accuracy.  Explicitly declaring floating point accuracy
  570. should yield more reliable, efficient and portable code.
  571.  
  572. 5.3.4.2  Fixed point types.  Fixed point types should be expressed with the
  573. constraints and boundaries appropriate for the identifier.  Explicitly
  574. stating these parameters, as noted with floating point types, enhances the
  575. portability because the type will be code dependent instead of machine
  576. dependent.
  577.  
  578.  
  579. 5.3.5  Record types.
  580.          a.  A record type is preferred when each component can be sensibly
  581. named, the components do not need to be dynamically indexed, and the
  582. combination of components is needed to provide full meaning to the type, e.g.
  583.  
  584.              type COMPLEX is
  585.                record
  586.                  Real        : REAL := 0.0;
  587.                  Imaginary   : REAL := 0.0;
  588.                end record;
  589.  
  590. "COMPLEX" needs both the Real and the Imaginary part to have meaning.
  591. Whereas, arrays are useful when one or more component(s) are primary over
  592. others, or access is needed via indexing, e.g.
  593.  
  594.              type WORK_DAY is (MON, TUE, WED, THU, FRI, SAT, SUN, HOL);
  595.              type DOLLARS is array (5 .. 7) of INTEGER;
  596.              type OVERTIME is array (WORK_DAY) of DOLLARS;
  597.  
  598. Once the dollars are "loaded" into OVERTIME, computations, etc. will be
  599. easier than having to scan records for the appropriate OVERTIME.
  600.  
  601.          b.  Overcomplicated record structures should be avoided by grouping
  602. related data into subrecord types.
  603.  
  604.              type COORDINATE is
  605.                record
  606.                  Row      : INTEGER range 1 .. 20;
  607.                  Column   : INTEGER range 1 .. 30;
  608.                end record;
  609.  
  610.              type WINDOW is
  611.                record
  612.                  Top_Left      :   COORDINATE;
  613.                  Bottom_Right  :   COORDINATE;
  614.                end record;
  615.  
  616.          c.  Discriminants.  Discriminants should be used whenever the object
  617. has closely related variances which would more easily be understood tied to
  618. a single data type, e.g.
  619.  
  620.              type BUFFER (Size : BUFFER_SIZE := 100) is
  621.                record
  622.                  Position  : BUFFER_SIZE := 0;
  623.                  Value     : STRING (1 .. Size);
  624.                end record;
  625.  
  626. A record component may or may not depend on the discriminant.  In the above
  627. example, the component Value depends on the discriminant Size for its upper
  628. boundary.
  629.  
  630.          d.  Enumeration types should be used for discriminants of record
  631. variants  whenever possible.  A discriminant should generally have a default
  632. initialization only if the discriminant value is intended to change over the
  633. lifetime of an object.
  634.  
  635.          e.  Variant parts.  One of the strong features of Ada is the use of
  636. variants in defining alternate lists of components.  This is good software
  637. engineering practice because all possible uses of a discriminant are defined
  638. and in one location, with the constraints being specified in the variable or
  639. a subtype declaration, e.g. (from the Standard)
  640.  
  641.            type DEVICE  is (PRINTER, DISK, DRUM);
  642.            type STATE   is (OPEN, CLOSED);
  643.  
  644.            type PERIPHERAL (Unit : DEVICE := DISK) is
  645.              record
  646.                Status  : STATE;
  647.                case Unit is
  648.                  when PRINTER => Line_Count   : LINE_RANGE;
  649.                  when others  => Cylinder     : CYLINDER_INDEX;
  650.                                  Track        : TRACK_NUMBER;
  651.                end case;
  652.              end record;
  653.  
  654. In this example, a general record type is made for the three types of
  655. peripheral units.  From there, subtypes can be created of specific
  656. peripheral units, e.g.
  657.  
  658.              subtype DRUM_UNIT is PERIPHERAL (DRUM);
  659.  
  660. If a constraint was not stated in a subtype or variable declaration, the
  661. compiler would assume the default of DISK.
  662.  
  663. 5.3.6  Access types.
  664.  
  665.          a.  Generally, access types should not be used when static types and
  666. stack allocation would be sufficient.
  667.  
  668.          b.  Generally access types should be used only when it is necessary
  669. to have data structures with dynamic pointers or to dynamically create
  670. objects.  However, access types may be needed for static objects if this leads
  671.  
  672. to a more consistent programming style (e.g., so that similar static and
  673. dynamic objects are treated identically).  For example, if linked lists are
  674. used in a program, there may be some lists which are constant, but which are
  675. still implemented as linked lists using access types.  This would allow, for
  676. example, passing these constant lists to subprograms which also handle dynamic
  677.  
  678. lists.
  679.  
  680. REAL_TIME:  There are certain instances where it is desirable to use access
  681. types to address static objects in embedded real-time applications.  Certain
  682. Ada compilers support only limited types of parameters when pragma INTERFACE
  683. is used (to assembly language, C, or some other language selected for
  684. efficiency or interface requirements), and access types are usually one of
  685. those supported when other static types, such as record structures, are not.
  686.  
  687. 5.3.7  Object declarations.
  688.  
  689.     a.  A single object declaration should be used to gather objects of the
  690. same type, e.g.
  691.  
  692.     Table Size,
  693.     Table Index,
  694.     Current Entry
  695.       : TABLE_RANGE;
  696.  
  697.     b.  An object should not be declared using a unnamed constrained array
  698. definition.
  699.  
  700. The unnamed array definition is the only case in Ada where an object can be
  701. declared to be of a type which does not have a name.  Instead, the array type
  702. should be named in an array type declaration, and that name used in the object
  703. declaration, even if there is only one object declared of that type.
  704.  
  705.     type POOL_TYP is
  706.       array (POOL_RANGE) of CHARACTER;
  707.  
  708.     POOL
  709.       : POOL_TYP;
  710.  
  711.     c.  Objects should generally be initialized.  Where possible, objects
  712. should always be initialized by their declaration, rather than in later code.
  713.  
  714.     Is_Found
  715.       : BOOLEAN  := FALSE;
  716.  
  717. 5.3.8  Formatting of declarations and types.
  718.  
  719.  
  720. 5.3.8.1  Commenting.
  721.  
  722.     a.  Type declarations (or groups of declarations) should be commented to
  723. indicate what is being defined, if that is not obvious from the type
  724. declaration itself.
  725.  
  726.     type VELOCITY is            -- Inertial velocity relative to the Earth
  727.       array (1 .. 3) of FLOAT;  -- Three test samples needed for comparison
  728.  
  729.     b.  Object declarations should always be commented if the object
  730. definition is unclear from the object and type identifiers alone.  Note
  731. that those properties of an object obtained from its type should not be
  732. repeated in comments on the object declaration.
  733.  
  734.     Spacecraft_Velocity         -- Spacecraft orbital velocity, assuming a
  735.       : VELOCITY;               -- circular orbit
  736.  
  737. 5.3.8.2  Indentation.  All declarations in a single declaration part should
  738. begin with the same indentation level.
  739.  
  740. 5.3.8.3  Type definitions.
  741.  
  742.     a.  Array type definitions should have one of the following formats:
  743.  
  744.     type <type name> is
  745.       array <index definition> of <subtype indication>;
  746.  
  747.     type <type name> is
  748.       array <index definition>
  749.         of <subtype indication>;
  750.  
  751.     b.  Record type definitions should have one of the following formats:
  752.  
  753.     type <type name> is
  754.       record
  755.         <component declaration>
  756.         <component declaration>
  757.       end record;
  758.  
  759.     type <type name>
  760.       ( <discriminant declaration>;
  761.         <discriminant declaration> ) is
  762.       record
  763.         <component declaration>
  764.         case <discriminant name> is
  765.           when <choices> =>
  766.             <component declaration>
  767.             <component declaration>
  768.  
  769.         end case;
  770.  
  771.       end record;
  772.  
  773.     c.  All <component declarations> and <discriminant declarations> should be
  774.  
  775. formatted like object declarations (see paragraph 5.3.8.4).
  776.  
  777.     d.  Other type definitions should be formatted as follows:
  778.  
  779.     type <type name> is
  780.       <type definition>;
  781.  
  782.     subtype <type name> is
  783.       <subtype indication>;
  784.  
  785.     e.  Long enumeration type definitions should be formatted into easily
  786. readable columns.
  787.  
  788. 5.3.8.4  Formatting of object declarations.
  789.  
  790.     a.  Object declarations should have one of the following formats.  The
  791. preferred formats are:
  792.  
  793.     <object name>
  794.       : <subtype indication> := <expression>;
  795.  
  796.     b.  When the subtype indication and/or expression is long, or when comments
  797.  
  798. are needed, it may be necessary to futher continue the declaration as follows:
  799.  
  800.     <object name>
  801.       : <subtype indication>    -- narrative explanation of subtype
  802.         := <expression>;
  803.  
  804.     c.  Declarations containing short identifiers may also be formatted all on
  805. one line, and is the perferred method when used as subordinate or supportive
  806. declarations, e.g.
  807.  
  808.     <object name>     : <subtype indication>     := <expression>;
  809.  
  810. In this case, all such declarations textually grouped together or appearing as
  811. components in a single record definition or in a single parameter list should
  812. have their ":" and ":=" symbols aligned.
  813.  
  814. 5.3.9  Examples for declarations and types.
  815.  
  816.  
  817. 5.3.9.1  Example 3X1.
  818.  
  819.     type SENSOR_ARRAY is
  820.       array (NATURAL range <>) of SENSOR;
  821.  
  822.     UARS_Sensors                         -- Sensor configuration for the
  823.       : SENSOR_ARRAY (1 .. Num_Sensors); -- UARS control system
  824.  
  825. 5.3.9.2  Example 3X2.
  826.  
  827.     type JULIAN_DATE_NUMERIC is
  828.       record
  829.         Two_Digit_Year   : INTEGER range 0 .. 99;
  830.         Numeric_Day      : INTEGER range 1 .. 366;
  831.       end record;
  832.  
  833. 5.3.9.3  Example 3X3.
  834.  
  835.     type DEVICE is
  836.       (PRINTER, DISK, DRUM);
  837.  
  838.     type STATE is       -- Operational state of a
  839.       (OPEN, CLOSED);   -- device.
  840.  
  841.     type PERIPHERAL
  842.       (Unit : DEVICE := DISK) is
  843.       record
  844.         Status : STATE;
  845.         case Unit is
  846.           when PRINTER     =>
  847.             Average_Lines_Per_Page : INTEGER range 1 .. Page_Size;
  848.           when DISK | DRUM =>
  849.             Cylinder       : CYLINDER_INDEX;
  850.             Track          : TRACK__NUMBER;
  851.         end case;
  852.       end record;
  853.  
  854. 5.4  Names and expressions
  855.  
  856.  
  857. 5.4.1  Aggregates.
  858.  
  859.     a.  Aggregates are preferable to individually setting all or most of the
  860. components of an array or record.
  861.  
  862.     b.  Named aggregates should be used where possible.
  863.  
  864. 5.4.2  Static expressions.  Being able to differentiate between static and
  865. universal expressions and their respective uses will assist in understanding
  866. different characteristics of software engineering practices, i.e. to
  867. maximize accuracy, static expressions should be used.  The detail can be
  868. provided to the depth desired, e.g.
  869.  
  870.        Pi     : constant := 3.141_592;
  871.        Two_Pi : constant := 6.283_185;
  872.  
  873. Whereas, understandability and readability are increased using universal
  874. expressions, e.g.
  875.  
  876.        Half_Pi     : constant := Pi / 2.0;
  877.        Deg_To_Rad  : constant := Half_Pi / 90.0;
  878.        Rad_To_Deg  : constant := 1.0 / Deg_To_Rad;
  879.  
  880. NOTE:  Two_Pi could have been gained by the expression   Pi * 2.0; however,
  881. if accuracy is needed to six decimal places, the static expression must be
  882. used or the original Pi would have to show additional decimal places. (The
  883. seventh decimal value for Pi is a 6; therefore, doubling Pi, the sixth
  884. decimal is a 5, not a 4 as would be obtained).
  885.  
  886. 5.4.3  Short-circuit control.
  887.  
  888.     a.  Short-circuit control forms should generally be used only to avoid
  889. evaluation of an undefined or illegal expression.  Short circuit operators
  890. should not be used to optimize execution.
  891.  
  892.     (N /= 0) and then (Total/N > Limit)
  893.  
  894.     (Index = 0) or else User(Index).Not_Available
  895.  
  896.     b.  The short-circuit control forms should be used to signal to a human
  897. reader that the correctness of the second condition depends on the results of
  898. the first.  They should not be used for micro-efficiency reasons, concerns
  899. better handled by an optimizing compiler.  If efficiency considerations are
  900. substantially important, "if" statements should be used instead of the short-
  901. circuit forms with functions used to avoid repeated code, if necessary.
  902.  
  903. REAL_TIME:  Memory considerations are a concern; therefore, the opposite
  904. should be true, i.e. short-circuits should be used over "if" statements.
  905.  
  906. 5.4.4  Type qualification.
  907.  
  908.     a.  An explicit type conversion should not be used if a type qualified
  909. expression is meant.
  910.  
  911.         Good :  LONG_FLOAT'(3.141_59)
  912.         Bad  :  LONG_FLOAT (3.141_59)
  913.  
  914. A qualified expression is used to state explicitly the type, and possibly sub-
  915. type, of a value.  A type conversion, however, results in the dynamic
  916. conversion of a value to a target type.  Sometimes a type conversion can be
  917. used to serve the purpose of a type qualification.  However, if the operand is
  918. already of the desired base type, a conversion is not really necessary and a
  919. qualification should be used instead.
  920.  
  921.     b.  Type qualification should be avoided if possible, especially when
  922. the type of an enumeration literal or aggregate is not known from context.
  923. For example:
  924.  
  925.     type COLOR is
  926.       (BLACK, RED, GREEN, BLUE, WHITE);
  927.  
  928.     type LIGHT is
  929.       (RED, YELLOW, GREEN);
  930.  
  931.     procedure Set
  932.       ( Color_Code : in COLOR );
  933.  
  934.     procedure Set
  935.       ( Color-_Code : in LIGHT );
  936.     ...
  937.  
  938.     Set (COLOR'(RED));   -- Type qualification must be used here to
  939.     Set (LIGHT'(RED));   -- resolve the overloading of Set and RED
  940.  
  941. It would be better in this case to rename one of the Set procedures
  942. or to at least give them different parameter names so the overloading
  943. could be resolved using name notation.
  944.  
  945. 5.4.5  Formatting of names and expressions.
  946.  
  947. 5.4.5.1  Names.
  948.  
  949.     a.  The name for a type should be a common noun indicating the class of
  950. the objects it contains.
  951.  
  952.     DEVICE
  953.     AUTHORITY_LEVEL
  954.     USER_NAME
  955.     PHONE_LIST
  956.  
  957. A type name should end with the suffix "_TYP" if convolution will develop
  958. among other types (enumeration, etc.) with the same name.
  959.  
  960.     EMPLOYEE_TYP
  961.     SCHEDULE_TABLE_TYP
  962.     COLOR_TYP
  963.  
  964. NOTE:  The POSIX/Ada committee has recommended the suffix "_TYPE" not be used
  965. because of various problems, and it will not be used in the Ada/POSIX
  966. interface standard.
  967.  
  968.     b.  The names of non-BOOLEAN valued objects should be nouns, preferably
  969. more precise than the names of types.
  970.  
  971.     Current_User
  972.       : USER_NAME;
  973.  
  974.     Output_Device
  975.       : DEVICE;
  976.  
  977.     Schedule_Table
  978.       : SCHEDULE_TABLE_TYP;
  979.  
  980.     New_Employee
  981.       : EMPLOYEE_TYP;
  982.  
  983. BOOLEAN valued objects should have predicate-clause (e.g., "Is Open") or
  984. adjective names.
  985.  
  986.     User_Is_Available
  987.     List_Empty
  988.     Done
  989.     Not_Ready
  990.     Is_Waiting
  991.  
  992. 5.4.5.2  Parentheses.  Syntactically redundant parentheses should generally be
  993. used to enhance the readability of expressions, especially by indicating the
  994. order of evaluation.  This is true even for single expressions where operators
  995. of different precedence levels are present.
  996.  
  997. For example:
  998.  
  999.     Variance := (Roll_Error ** 2) + ((Yaw_Error ** 2) / 2);
  1000.  
  1001.  
  1002. 5.4.5.3  Aggregates format.
  1003.  
  1004.     a.  When longer than two components, or whenever readability is
  1005. improved, named aggregates should be formatted as indicated below, with one
  1006. association per line and the "=>" arrows aligned.
  1007.  
  1008.     Output_Device :=  ( Device         => DISK,
  1009.                         Status         => CLOSED,
  1010.                         Cylinder       => 1,
  1011.                         Track          => Startup_Track_Num );
  1012.  
  1013.     b.  Aggregates for multidemensional arrays may be formatted in a
  1014. tabular fashion to enhance readability.
  1015.  
  1016. 5.5  Statements.
  1017.  
  1018.  
  1019. 5.5.1  Slice Statements.  Array slice assignments should be used rather than
  1020. loops to copy all or part of an array.  This is more readable and less error
  1021. prone, especially in the case of slices with overlapping ranges.
  1022.  
  1023.     Client_List (Last_Client .. Number_Of_Clients) :=
  1024.       New_Clients (1 .. Num_New_Clients)
  1025.  
  1026. NOTE: on format - array elements should stay with the array name, which is
  1027. why a left-right format was not used in this instance (line too long).
  1028.       on syntax - array slice assignments work properly only if both arrays
  1029. are of the same type.
  1030.  
  1031. 5.5.2  If statements.  An "if" statement should not be used to create the
  1032. effect of a "case" statement controlled by the value of an enumeration type
  1033. other than BOOLEAN.
  1034.  
  1035. 5.5.3  Case statements.
  1036.  
  1037.     a.  A "case" statement should be controlled by an enumeration type, not
  1038. by a BOOLEAN value.
  1039.  
  1040.     b.  When possible, the explicit listing of all choices on a "case"
  1041. statement is preferable to the use of an "others" clause.
  1042.  
  1043. This makes it easier for a human reader to see that the proper actions are
  1044. being taken in all cases.  Further, if the enumeration type of the control
  1045. expression is modified, the compiler will indicate overlooked alternatives.
  1046. However, there are cases when an "others" clause makes sense.  For example, if
  1047. the control expression is of type character, then it is usually best to use an
  1048. "others" clause to handle the "undesired characters" case.
  1049.  
  1050. 5.5.4  Block statements.
  1051.  
  1052.     a.  Blocks should be used cautiously to introduce local declarations or to
  1053. define a local exception handler.  Resources for data local to the block are
  1054. allocated only when the block is entered (elaborated).  This is a fundamental
  1055. difference between procedures and blocks.  A procedure is callable by any
  1056. number of other program units while a block is limited in scope to its
  1057. immediate lexical level and cannot be called.
  1058.  
  1059. To some extent, a block can be thought of as a procedure which is hard coded
  1060. in-line.  However, a procedure call contributes to readability precisely by
  1061. not having its source code in-line (providing a "functional abstraction").
  1062. Therefore, blocks should always be used cautiously and only for specific
  1063. purposes.  Thought should always be given to using a procedure call instead of
  1064. a block to improve readability.
  1065.  
  1066.     b.  Declarations of objects used only within a block should be nested
  1067. within the block.
  1068.  
  1069. REAL_TIME:  Procedure calls require substanial execution time overhead.  A
  1070. potential run-time efficiency advantage of blocks is memory savings.  If a
  1071. declare statement is used in the block, the resources for data which are local
  1072. to the block will only be allocated when the block is entered.  Additionally,
  1073. some compilers may deallocate these memory resources after the block is exited.
  1074.  
  1075.  
  1076. 5.5.5  Exit statements.  "Exit" statements should be used cautiously, and
  1077. only when they significantly enhance the readability of the code.  If used,
  1078. the exit statement should use the name of the loop it is exiting.
  1079.  
  1080. It is often more readable to use exit than to try to add BOOLEAN variables to
  1081. a "while" loop condition to simulate exits form the middle of a loop.
  1082. However, it can be difficult to understand a program where loops can be
  1083. exited from multiple places.  It is best to limit the use of "exit" statements
  1084. to one per loop, if possible, and it is generally more readable to use "exit
  1085. when."  Use "if...then...exit; end if" when "last wishes" processing is needed.
  1086.  
  1087.  
  1088. REAL_TIME:  "Exit"s should not be used because they can greatly increase run
  1089. time if the code at the exit address has to be paged into working space.
  1090.  
  1091. 5.5.6  Return statements.  It is preferable to minimize the number of return
  1092. points from a subprogram, as long as this does not distract from the natural
  1093. structure or readability of the subprogram.
  1094.  
  1095. 5.5.7  Goto statements.  It is deemed as poor programming practice to use
  1096. "goto" statements.
  1097.  
  1098. Use of the "goto" makes the textual structure of code less reflective of its
  1099. logical structure.  Possible uses of the "goto" statement can always be
  1100. handled by other constructs in Ada, such as a procedure call or via an exit.
  1101.  
  1102. 5.5.8  Formatting of statements.
  1103.  
  1104. 5.5.8.1  Statement sequences.  Blank lines should be used liberally to break
  1105. sequences of statements into short, meaningful groups (see paragraph 5.2.2.6).
  1106.  
  1107.     Put_Line ("Welcome to the Electronic Message System");
  1108.  
  1109.     Logon_User (Current User);
  1110.     User_Directory.Lookup
  1111.       ( User_Name    => Current_User
  1112.         Authority    => User_Authority );
  1113.  
  1114.     if User_Authority = SPECIAL then
  1115.       Put_Line ("** You have SPECIAL authorization **");
  1116.     end if;
  1117.  
  1118. 5.5.8.2  If statement format.
  1119.     a.  "If" statements should have the following format:
  1120.  
  1121.     if <condition> then
  1122.       <statement>
  1123.       <statement>
  1124.     elsif <condition> then
  1125.       <statement>
  1126.       <statement>
  1127.     else
  1128.       <statement>
  1129.       <statement>
  1130.     end if;
  1131.  
  1132.     b.  Multiple conditions in an "if" clause should be grouped together,
  1133. placed on appropriate lines, and aligned so as to enhance clarity.
  1134.  
  1135. 5.5.8.3  Case statement format.  "Case" statements should have the following
  1136. format:
  1137.  
  1138.     case <expression> is
  1139.       when <choices> => <statement>
  1140.       when others    => <statement>
  1141.     end case;
  1142.  
  1143.     case <expression> is
  1144.       when <choices> =>
  1145.         <statement>
  1146.         <statement>
  1147.       when others =>
  1148.         <statement>
  1149.         <statement>
  1150.     end case;
  1151.  
  1152. 5.5.8.4  Loop statement format.
  1153.  
  1154.     a.  "Loop" statements should have one of the following formats:
  1155.  
  1156.     <loop name>:
  1157.     <iteration scheme> loop
  1158.       <statement>
  1159.       <statement>
  1160.     end loop <loop name>;
  1161.  
  1162.     b.  A loop should preferably have a loop identifier.
  1163.  
  1164. 5.5.8.5  Block statement format.
  1165.  
  1166.     a.  Block statements should have the following format:
  1167.  
  1168.     <block name>:
  1169.     declare
  1170.       <declaration>
  1171.       <declaration>
  1172.     begin
  1173.       <statement>
  1174.       <statement>
  1175.     exception
  1176.       when <exceptions> =>
  1177.         <statement>
  1178.         <statement>
  1179.     end <block name>;
  1180.  
  1181.     b.  Blocks should always have a block identifier.
  1182.  
  1183. 5.5.9  Examples for statements.
  1184.  
  1185. See also examples 5.9.14.2, 5.9.14.3, 5.9.14.4, 5.14.5.1, and 5.14.5.2.
  1186.  
  1187. 5.5.9.1  Example 5X1.
  1188.  
  1189.     if Security_Level = 0 then                 -- appropriate comments
  1190.       Message_Classification :=UNCLASSIFIED;   -- should be placed here
  1191.  
  1192.     elsif Security_Level > User_Clearance then -- stating what's going
  1193.       Message_Classification := PROTECTED;     -- on
  1194.  
  1195.     else
  1196.       Message_Classification := Classification (Security_Level);
  1197.  
  1198.     end if;
  1199.  
  1200. 5.5.9.2  Example 5X2.
  1201.  
  1202.     case Sensor is
  1203.       when ELEVATION => Record_Elevation (Sensor_Value);    -- <comments>
  1204.       when AZIMUTH   => Record_Azimuth (Sensor_Value);
  1205.       when DISTANCE  => Record Distance (Sensor_Value);
  1206.     end case;
  1207.  
  1208. 5.5.9.3  Example 5X3.
  1209.  
  1210.      Read_File:
  1211.      while not Text_IO.End_Of_File (File 1) loop
  1212.        Text_IO.Get (File1, Next_Record);    -- <comments>
  1213.        Store_Record (Next_Record);
  1214.      end loop Read_File;
  1215.  
  1216.      Compute_Total_Taxes:
  1217.      while Next /= Head loop
  1218.        Total_Taxes := Total_Taxes + Next.Pay_Period Deductions;
  1219.        Next :=  Next.Successor;
  1220.      end loop Compute_Total_Taxes;
  1221.  
  1222.      Merge Files:
  1223.      for N in 1 .. Max_Num_Files loop
  1224.        Get_Items:
  1225.        for J in 1 .. Max_Num_Items loop
  1226.          Get_New_Item (New_Item);
  1227.          Merge_Item (New_Item, Storage_File);
  1228.          exit Merge_Files when New _Item = Terminal Item;
  1229.        end loop Get_Items;
  1230.      end loop Merge_Files;
  1231.  
  1232. 5.5.9.4  Example 5X4.
  1233.  
  1234.     Swap_Integers:
  1235.     declare
  1236.       Temp : constant INTEGER := U;
  1237.     begin  -- Swap_Integers;
  1238.       U := V;
  1239.       V := Temp;
  1240.     end Swap_Integers;
  1241.  
  1242.     Check_Entry:
  1243.     begin
  1244.       Int IO.Get (Value);
  1245.       Update (Value);
  1246.     exception
  1247.       when Data Error =>
  1248.         Text_IO.New_Line;
  1249.         Text_IO.Put_Line ("Value entry error.");
  1250.         Entry_Error_Flag := TRUE;
  1251.     end Check_Entry;
  1252.  
  1253. 5.6  Subprograms.
  1254.  
  1255.  
  1256. 5.6.1  Cohesion.  A subprogram should perform a single, conceptual action
  1257. (i.e., should be "functionally cohesive").
  1258.  
  1259. The use of a subprogram increases readability by hiding the details of how an
  1260. action is performed and giving it a descriptive name.  A subprogram should
  1261. perform only a single conceptual action so that its use can be understood as
  1262. independently as possible from its implementation details and it can be given
  1263. a self-documenting name.  Note that simply shortening a program by placing
  1264. "repeated code" into subprograms must be considered a secondary goal.  Thus it
  1265. is quite acceptable to have subprograms which are only called at one place, so
  1266. long as those programs define cohesive actions.
  1267.  
  1268. NOTE:  Explicit parameter passing is the best way to build interfaces to
  1269. subprograms.  This method keeps the affected variables clearly defined and
  1270. visible.  Intensional use of side effects is considered poor programming
  1271. practice and should be used on a limited basis.  If used, side effects should
  1272. be extensively commented ... where they are taking place and where they are
  1273. affected.
  1274.  
  1275. 5.6.2  Parameters.
  1276.  
  1277.     a.  Subprograms with equivalent parameters should generally declare each
  1278. parameter in the same position with the same identifier.
  1279.  
  1280.     b.  Parameters with default expressions should be used only when they have
  1281. very well known default values and/or they are defaulted most of the time,
  1282. with the default being over-ridden only in special circumstances.  Great care
  1283. should be taken in using defaults, insuring the "mixing" of default and named
  1284. parameters does not disrupt the understandability and readability of the code.
  1285.  
  1286.     c.  Parameters with default expressions should generally be placed at the
  1287. end of the parameter list, so that they may be omitted if desired in calls
  1288. using positional notation.
  1289.  
  1290.     d.  As noted in the section for naming (5.2.2.4), parameters should
  1291. follow a similar schema, chosen to promote readability of the subprogram
  1292. calls, and where possible, should reflect the mode of the parameter.
  1293.  
  1294. 5.6.3  Recursion.  A recursive subprogram should generally be used only if
  1295. it is conceptually simpler for a given problem than a corresponding iterative
  1296. subprogram.
  1297.  
  1298. Many people have difficulty in understanding a program which uses recursion
  1299. extensively.  However, there are many cases where a recursive solution is
  1300. considerably simpler and clearer than an iterative one.  This is especially
  1301. true, for example, for traversing complicated data structures such as tree and
  1302. graph structures.
  1303.  
  1304. 5.6.4  Functions.  A subprogram without side-effects returning a single
  1305. value should generally be written as a function.  Since functions can be called
  1306. from within expressions, there is more freedom in how a function can be used.
  1307. For example, if a function is to be called only once within some other
  1308. subprogram, it can be used to initialize a constant object.
  1309.  
  1310.     procedure Process_Sensor Data is
  1311.       Main_Sensor_Data
  1312.         : constant SENSOR_DATA := Read_Sensor (Main_Sensor_Index);
  1313.  
  1314.     begin
  1315.       ...
  1316.  
  1317. However, if this sort of freedom is specifically not desired, or if the
  1318. subprogram has side effects, then use of a procedure should be considered
  1319. instead of a function, even if the subprogram returns only a single value.
  1320.  
  1321. 5.6.5  Overloading.
  1322.  
  1323.     a.  Overloading of subprograms should not be done. Use a meaningful
  1324. function name instead.   Possible (a weak possible) exceptions are the
  1325. following cases:
  1326.  
  1327.         (1) Widely used utility subprograms which perform identical or very
  1328. similar actions on arguments of different types (e.g., square-root of integer
  1329. and real arguments).
  1330.  
  1331.         (2)  Overloading of operator symbols.
  1332.  
  1333. Note that this is not meant to cover subprograms with identical names in
  1334. different packages, unless both subprograms are visible through "use" clauses
  1335. for their packages.
  1336.  
  1337.     b.  Operator symbols should be overloaded only when the new operator
  1338. definitions comply closely with the traditional meaning of the operator (e.g.,
  1339. "+" for vector addition).
  1340.  
  1341. 5.6.6  Formatting of subprograms.
  1342.  
  1343.  
  1344. 5.6.6.1  Subprogram names.
  1345.  
  1346.     a.  Except as indicated below, a subprogram name should be an imperative
  1347. or interrogatory verb phrase describing its action.
  1348.  
  1349.     Action_Complete
  1350.     Obtain_Next_Token
  1351.     lncrement_Line_Counter
  1352.     Create_New Group
  1353.  
  1354.      b.  Non-BOOLEAN valued function names may also be noun phrases.
  1355.  
  1356.      Top_Of_Stack
  1357.      X_Component
  1358.      Successor
  1359.      Sensor_Reading
  1360.  
  1361.      c.  BOOLEAN valued functions should have predicate-clause names.
  1362.  
  1363.      Stack_Is_Empty
  1364.      Last_Item_Check
  1365.      Device_Not_Ready
  1366.  
  1367. 5.6.6.2  Subprogram header.  Each subprogram specification, body or stub
  1368. should be preceded by a header comment block containing at least the
  1369. subprogram name and the indication SPEC, BODY, SPEC & BODY, STUB or SUBUNIT.
  1370.  
  1371.        --  ............................
  1372.        --  .                          .
  1373.        --  .     Obtain_Next_Token    .     SPEC
  1374.        --  .                          .
  1375.        --  ............................
  1376.  
  1377. 5.6.6.3  Subprogram declarations.
  1378.  
  1379.      a.  Procedure declarations should have the following format:
  1380.  
  1381.      -- <subprogrammer header>
  1382.  
  1383.      procedure <procedure identifier>
  1384.        ( <parameter specification>;
  1385.          <parameter specification> );
  1386.  
  1387.      --  <documentary comments>
  1388.  
  1389.  Each <parameter specification> should be formatted like an object declaration
  1390. (see paragraph 5.3.8.4).  The documentary comments should follow guideline d.,
  1391. below.
  1392.  
  1393.     b.  Function declaration should have the following format:
  1394.  
  1395.      -- <subprogrammer header>
  1396.  
  1397.      function <function designator>
  1398.        ( <parameter specification>;
  1399.          <parameter specification> )
  1400.        return <type mark>;
  1401.  
  1402.      --  <documentary comments> Each <parameter specification> should be
  1403. formatted like an object declaration (see paragraph 5.3.8.4).  The
  1404. <documentary comments> should follow guideline d., below.
  1405.  
  1406.     c.  Parameter mode indications should always be used in procedure
  1407. specifications.  In a function specification, mode indications should either
  1408. be used for all of the parameters or none of the parameters.
  1409.  
  1410.     d.  Subprogram declarations should be followed by at least the following
  1411. documentation:
  1412.  
  1413.   --  PURPOSE   <--headings can be upper or lower case
  1414.   --  A description of all purposes and functions of the subprogram.
  1415.   --
  1416.   --  EXCEPTIONS
  1417.   --  A list of all exceptions which may propagate out of the subprogram,and
  1418.   --  a description of when each would be raised.
  1419.   --
  1420.   --  NOTES
  1421.   --  Additional comments on the use of the subprogram, references, etc.
  1422.  
  1423. The "Exceptions" and "Notes" headings should be included even if these
  1424. sections are empty.  An empty section may be indicated by placing the
  1425. annotation "(none)" after the appropriate header.  Only in the case that the
  1426. subprogram declaration is a compilation unit, the following section should be
  1427. added to the documentation:
  1428.  
  1429.   --  MODIFICATIONS
  1430.   --  A list of modifications made to the subprogram DECLARATION.
  1431.   --  Each entry in the list should include the date of the change,
  1432.   --  the name of the person who made the change and a description
  1433.   --  of the modification.  The first entry in the list should
  1434.   --  always be the initial coding of the subprogram declaration.
  1435.  
  1436. 5.6.6.4  Subprogram bodies and stubs.
  1437.  
  1438.     a.  Subprogram bodies should have the following format if not standalone:
  1439.  
  1440.     separate (<parent name>)
  1441.     <subprogram specification> is
  1442.  
  1443.     --  <documentary comments>
  1444.  
  1445.       <declaration>
  1446.       <declaration>
  1447.  
  1448.     begin  -- <subprogram name>
  1449.  
  1450.       <statement>
  1451.       <statement>
  1452.     exception
  1453.       when <exceptions> =>
  1454.         <statement>
  1455.     end <subprogram name>;
  1456.  
  1457. The <subprogram specification> should be formatted as in a subprogram
  1458. declaration (see paragraph 5.6.6.3).  The <documentary comments> should follow
  1459. guide- line b., below.  Note that the "end" of a subprogram should always
  1460. include the subprogram name.
  1461.  
  1462.     b.  Subprogram bodies should have AT LEAST the following documentation
  1463. placed immediately after the subprogram header:
  1464.  
  1465.   --  NOTES
  1466.   --  Comments on the design, implementation and use of the
  1467.   --  subprogram.
  1468.  
  1469. The "NOTES" heading should be included even if the section is empty.  An empty
  1470. section may be indicated by the comment "Notes (none)." Only in the case of a
  1471. subprogram body which is a separate compilation unit from its specification,
  1472. the following section should be added to the documentation.
  1473.  
  1474.   --  MODIFICATIONS
  1475.   --  A list of modifications made to the subprogram BODY.
  1476.   --  Each entry in the list should include the date of the change,
  1477.   --  the name of the person who made the change and a description
  1478.   --  of the modification.  The description should identify exactly
  1479.   --  where in the compilation unit that the change was made.  The
  1480.   --  first entry in the list should always be the initial coding
  1481.   --  of the subprogram body.
  1482.  
  1483. If there is no declaration or stub for a subprogram, then the subprogram body
  1484. should also include all the documentation required for a subprogram
  1485. declaration (see paragraph 5.6.6.3).
  1486.  
  1487.     c.  Subprogram stubs should have the following format:
  1488.  
  1489. <subprogram specification> is separate;
  1490.  
  1491. where the <subprogram specification> is formatted as in a subprogram
  1492. declaration (see paragraph 5.6.6.3).  If there is no previous declaration for
  1493. a separate subprogram, then the subprogram stub should be followed by the same
  1494. documentary comments required for a subprogram declaration (see paragraph
  1495. 5.6.6.3).
  1496.  
  1497. 5.6.6.5  Named parameter association.
  1498.  
  1499.     a.  Named parameter association should generally be used for procedure
  1500. calls of more than a single parameter.  Positional parameters are generally
  1501. preferred for function calls.
  1502.  
  1503.     b.  Named and positional parameter associations should generally not be
  1504. mixed in a single subprogram call.
  1505.  
  1506.     c.  Named parameter associations should generally appear one to a line
  1507. with formal parameters, "=>" symbols and actual parameters aligned.
  1508.  
  1509.     Obtain_Next_Token
  1510.       ( File        => Current Source File,
  1511.         Position    => Current Column',
  1512.         Token       => Next_Token );
  1513.  
  1514. 5.6.7  Examples for subprograms.  See also examples 5.7.6.3, 5.9.14.3,
  1515. 5.12.7.1, 5.12.7.3, 5.14.5.1, and 5.14.5.2.
  1516.  
  1517. 5.6.7.1  Example 6X1.
  1518.  
  1519.        --  .............................
  1520.        --  .                           .
  1521.        --  .     Obtain_Next_Token     .   SPEC
  1522.        --  .                           .
  1523.        --  .............................
  1524.  
  1525.          procedure Obtain_Next_Token
  1526.            ( File      : in out Parser_Types.FILE;        -- sequential file
  1527.              Token     : out    Parser_Types_TOKEN_TYP;
  1528.              Position  : in     Parser_Types.COL_NUM_TYP := 0 );
  1529.  
  1530.   --  Purpose
  1531.   --  This procedure scans the current input line from the point at
  1532.   --  which it was last called and returns the next token.
  1533.   --
  1534.   --  Exceptions
  1535.   --
  1536.   --  Source_File_Not_Open  --  Raised if the input file is not open
  1537.   --  Notes (None)
  1538.  
  1539. 5.6.7.2  Example 6X2.
  1540.  
  1541.        --  ..........................
  1542.        --  .                        .
  1543.        --  .      Decode_Token      .    SPEC
  1544.        --  .                        .
  1545.        --  ..........................
  1546.  
  1547.     function Decode_Token
  1548.       ( File    : Parser_Types.FILE;
  1549.         Token   : Parser_Types.TOKEN_TYP )
  1550.           return Parser_Types.TOKEN_TYP;
  1551.  
  1552.   --  Purpose
  1553.   --  This function returns the ordinal value of the decoded token.
  1554.   --
  1555.   --  Exceptions
  1556.   --  Illegal Token  --  raised if the token is not legal
  1557.   --
  1558.   --  Notes
  1559.   --  This function will later be changed to a procedure.
  1560.  
  1561. 5.6.7.3  Example 6X3.
  1562.  
  1563.        --  ...............................
  1564.        --  .                             .
  1565.        --  .     Obtain_Next_Token       .     STUB
  1566.        --  .                             .
  1567.        --  ...............................
  1568.  
  1569.     procedure Obtain_Next_Token
  1570.       ( File      : in out Parser_Types.FILE;
  1571.         Token     : out    Parser_Types.TOKEN_TYP;
  1572.         Position  : in     Parser_Types. COL_NUM_TYP :=0 ) is separate;
  1573.  
  1574. 5.6.7.4  Example 6X4.
  1575.  
  1576.        --  .........................
  1577.        --  .                       .
  1578.        --  .    Decode_Token       .    STUB
  1579.        --  .                       .
  1580.        --  .........................
  1581.  
  1582.     function Decode_Token
  1583.       ( File   : Parser_Types.FILE;
  1584.         Token  : Parser_Types.TOKEN_TYP )
  1585.           return Parser_Types.TOKEN_TYP is separate;
  1586.  
  1587. 5.6.7.5  Example 6X5.
  1588.  
  1589.        --  ................................
  1590.        --  .                              .
  1591.        --  .     Obtain_Next_Token        .    SUBUNIT
  1592.        --  .                              .
  1593.        --  ................................
  1594.  
  1595.     with Parser_Types,
  1596.          File_Handler;
  1597.  
  1598.     separate (Lexical_Analyzer)
  1599.  
  1600.     procedure Obtain Next Token
  1601.       ( File      : in out Parser_Types.FILE;
  1602.         Token     : out    Parser_Types.TOKEN_TYP;
  1603.         Position  : in     Parser_Types.COL_NUM_TYP :=0 ) is
  1604.  
  1605.  
  1606.    --  Notes (None)
  1607.    --
  1608.    --  Modifications
  1609.    --  7/4/85   Rebecca DeMornay    Initial version of the subunit
  1610.    --  9/6/85   R. DeMornay         Added the local function
  1611.    --                               "Increment_Line_Counter".
  1612.  
  1613.   type LINE_COUNT is                       -- A count of the number
  1614.     range 1 .. File_Handler_Max Size;      -- of lines in a file.
  1615.  
  1616.     Line_Counter : LINE_COUNT := 1;
  1617.  
  1618.        --  ...............................
  1619.        --  .                             .
  1620.        --  .     Increment_Line_Counter  .    SPEC & BODY
  1621.        --  .                             .
  1622.        --  ...............................
  1623.  
  1624.   function Increment_Line_Counter
  1625.     ( File  : Parser_Types.FILE;
  1626.       Line  : LINE_COUNT )                  -- Line number in "File"
  1627.                                             -- at the time of call
  1628.     return LINE_COUNT is
  1629.  
  1630.   --  Purpose
  1631.   --  This function increments the line counter from the point at
  1632.   --  which it was after the last call of this routine.
  1633.   --
  1634.   --  Exceptions
  1635.   --  Source_File_Not_Open     -- Raised if "File" is not open.
  1636.   --  End_Of_File              -- Raised if the function is called and
  1637.   --                              the end of the file has already been
  1638.   --                              reached.
  1639.   --
  1640.   --  Notes (None)
  1641.  
  1642.   begin    -- Increment_Line_Counter
  1643.     ...
  1644.   end Increment_Line_Counter;
  1645.  
  1646.   begin    -- Obtain_Next_Token
  1647.   exception
  1648.     when File_Handler.FILE_ERROR => Token := Parse_Types.NONE;
  1649.       raise Source_File_Not_Open;
  1650.   end Obtain_Next_Token;
  1651.  
  1652. 5.7  Packages.
  1653.  
  1654.  
  1655. 5.7.1  Use of packages.
  1656.  
  1657.     a.  There are numerous roles for packages, the following represent the
  1658. most common:
  1659.  
  1660.         (1) Model an abstract entity (or data type) appropriate to the domain
  1661. of a problem.
  1662.  
  1663.         (2) Collect related type and object declarations which are used
  1664. together (this kind of package should generally be used only to provide a
  1665. common set of declarations for two or more library units).
  1666.  
  1667.         (3) To group together program units for essential configuration
  1668. control (packages fulfilling this role alone should be used sparingly).
  1669.  
  1670. The roles above are listed in order of decreasing desirability.  The first
  1671. role, modeling a problem domain entity, is the strongest use of packages for
  1672. structuring a program.  It corresponds to the requirement of functional
  1673. cohesion for subprograms (see paragraph 5.6.1) and contributes to the goal of
  1674. making the structure of a program reflect the structure of its problem domain.
  1675.  
  1676. The second kind of package, collection of related declarations, should
  1677. generally be used only to provide a common set of declarations for two or more
  1678. library units.  Further, it is better to minimize the declaration of variables
  1679. in these packages.  Overuse of packages of variables results in a FORTRAN
  1680. COMMON block style program decomposition which defeats the abstraction and
  1681. information hiding properties of packages (see paragraph 5.7.4).
  1682.  
  1683. Finally the last type of package, a grouping of units for configuration
  1684. reasons, should be used sparingly since it gives no additional information to
  1685. a human reader on the structure of the program.  This type of package might,
  1686. for example, be used to divide a large program at the top level into
  1687. subsystems to be developed by separate teams.  It would be best, however, if
  1688. these subsystem packages fulfilled, in addition, one of the other two roles.
  1689.  
  1690.     b.  Packages should NOT be designed based on the procedural structure of
  1691. the code which calls them.
  1692.  
  1693. For example, a group of procedures should not be packaged simply because they
  1694. are all called at system initialization, or because they are always called in
  1695. a certain sequence.  Such a package is closely coupled to the context in which
  1696. it is used and is not very understandable, reusable or maintainable as a unit.
  1697.  
  1698.     c.  A logical hierarchy of packages should be used to reflect or model
  1699. levels of abstraction.
  1700.  
  1701. 5.7.2  Nesting.  The use of nesting is not recommended because of the
  1702. numerous precautions and limitations involved.
  1703.  
  1704.  
  1705. 5.7.3  Initialization.  The initialization process should be self-contained.
  1706. It is poor programming practice to call from the initialization statement of
  1707. a package to subprograms outside the package and should be avoided.
  1708.  
  1709. 5.7.4  Visible variables.
  1710.  
  1711.     a.  Variable declarations in package specifications should be minimized.
  1712.  
  1713. One of the aspects of software engineering Ada supports so well is information
  1714. hiding.  The use of variables in a package specification generally reduces the
  1715. abstraction and information hiding properties of the package.  For example, a
  1716. variable cannot provide protection against being changed by units other than
  1717. the package.  Therefore it is generally better to use a function rather than a
  1718. variable to read data from a package.  It is also generally better to use a
  1719. procedure rather than a variable to give data to a package, since a variable
  1720. cannot trigger any package operations and a variable declaration often exposes
  1721. some internal data representation details of the package.
  1722.  
  1723.     b.  The private part of a package specification should only be used to
  1724. supply the full definitions of private types and deferred constants; all other
  1725. declarations should be put in the package body.
  1726.  
  1727.     c.  Object of private type should be initialized by default, if possible.
  1728.  
  1729. 5.7.5  Formatting of packages.
  1730.  
  1731. 5.7.5.1  Package names.  A package name should be a noun phrase describing the
  1732. abstract entity modeled by the package, or simply whatever is being packaged.
  1733.  
  1734.     Stack_Handler
  1735.     Vehicle_Controller
  1736.     Terminal_Operations
  1737.     Parser_Types
  1738.     Utilities_Package
  1739.  
  1740. 5.7.5.2  Package header.  Each package specification, body or stub should be
  1741. preceded by a header comment block containing at least the package name and
  1742. the indication SPEC, BODY, STUB or SUBUNIT.  A suggested format follows:
  1743.  
  1744.        --  ***************************
  1745.        --  *                         *
  1746.        --  *    Lexical_Analyzer     *   SPEC
  1747.        --  *                         *
  1748.        --  ***************************
  1749.  
  1750. 5.7.5.3  Package specifications.
  1751.  
  1752.     a.  Package specifications should have the-following format:  package
  1753. <package identifier> is
  1754.  
  1755.     --  <documentary comments>
  1756.  
  1757.       <declaration>
  1758.       <declaration>
  1759.  
  1760.     private  -- <package identifier>
  1761.  
  1762.       <declaration>
  1763.       <declaration>
  1764.  
  1765.     end <package identifier>;
  1766.  
  1767. The <documentary comments> should follow guideline b., below.  Note that the
  1768. <package identifier> should always be repeated at the "end" of the package
  1769. specification.
  1770.  
  1771.     b.  A package specification should include AT LEAST the following
  1772. documentation immediately after the package header:
  1773.  
  1774.    --  Purpose
  1775.    --  A description of the purpose and function of the package.
  1776.    --
  1777.    --  Initialization Exceptions
  1778.    --  A list of all exceptions which may propagate out of the
  1779.    --  package INITIALIZATION PART and a description of when each
  1780.    --  would be raised.
  1781.    --
  1782.    --  Notes
  1783.    --  Additional comments on the use of the package.
  1784.  
  1785. The "Initialization Exceptions" and "Notes" headers should be included even if
  1786. these sections are empty.  An empty section may be indicated by placing the
  1787. annotation "(none)" after the appropriate header.  Only in the case a package
  1788. specification which is a compilation unit, the following section should be
  1789. added to the documentation:
  1790.  
  1791.   --  Modifications
  1792.   --  A list of modifications made to the package SPECIFICATION.
  1793.   --  Each entry in the list should include the date of the change,
  1794.   --  the name of the person who made the change and a description
  1795.   --  of the modification.  The description should indicate exactly
  1796.   --  where in the compilation unit that the change was made.  The
  1797.   --  first entry in the list should always be the initial coding of
  1798.   --  the package specification.
  1799.  
  1800.     c.  In a declarative part, all package specifications should appear before
  1801. any package or task bodies.
  1802.  
  1803. 5.7.5.4  Package bodies and stubs.
  1804.  
  1805.     a.  Package bodies should have the following format:
  1806.  
  1807.     separate (<parent name>)
  1808.     package body <package identifier> is
  1809.  
  1810.     --  <documentary comments>
  1811.  
  1812.       <declaration>
  1813.       <declaration>
  1814.  
  1815.     begin -- <package identifier>
  1816.  
  1817.       <statement>
  1818.       <statement>
  1819.  
  1820.     exception
  1821.       when <exception> =>
  1822.         <statement>
  1823.  
  1824.     end <package identifier>;
  1825.  
  1826. The <documentary comments> should follow guideline b below.  Note that the
  1827. <package identifier> should always be repeated at the "end" of the package
  1828. body.
  1829.  
  1830.     b.  A package body should have at least the following documentation placed
  1831. immediately after the package header:
  1832.  
  1833.   --  Notes
  1834.   --  Comments on the design, implementation and use of the
  1835.   --  package.
  1836.  
  1837. The "Notes" header should be included even if the section is empty.  An empty
  1838. section may be indicated by the comment "Notes (none)." Only in the case of a
  1839. package body which is a compilation unit, should the following section be
  1840. added to the documentation:
  1841.  
  1842.   --  Modifications
  1843.   --  A list of modifications made to the package BODY.  Each
  1844.   --  entry in the list should include the date of the change,
  1845.   --  the name of the person who made the change and a
  1846.   --  description of the modification.  The description should
  1847.   --  indicate exactly where in the compilation unit that the
  1848.   --  change was made.  The first entry in the list should always
  1849.   --  be the initial coding of the package body.
  1850.  
  1851.     c.  Package stubs should have the following format:  package body <package
  1852. identifier> is separate;
  1853.  
  1854. 5.7.6  Examples for packages.
  1855.  
  1856.          See also example 5.12.7.3
  1857.  
  1858. 5.7.6.1  Example 7X1.
  1859.  
  1860.        --  ***************************
  1861.        --  *                         *
  1862.        --  *    Lexical Analyzer     *    SPEC
  1863.        --  *                         *
  1864.        --  ***************************
  1865.  
  1866.     with Basic_Types,
  1867.          Parser_Types;
  1868.  
  1869.     package Lexical_Analyzer is
  1870.  
  1871.    --  Purpose
  1872.    --  The routines in this package read the source program, one
  1873.    --  character at a time, to generate a stream of tokens.  As each
  1874.    --  token is produced it is passed to the package "Parser." The
  1875.    --  legal tokens are defined in the Language Reference Manual.
  1876.    --
  1877.    --  Initialization Exceptions
  1878.    --
  1879.    --  Diana_ File_ Non_Existent -- Raised if the file "DIANA.ADA"
  1880.    --                               does not exist
  1881.    --  Notes
  1882.    --  Tokens are limited to 32 characters in length.  Also, only
  1883.    --  sequential text files can be operated on by the parser.
  1884.    --  Modifications
  1885.    --
  1886.    --  6/14/85  Rebecca DeMornay   Initial version of spec
  1887.    --  8/26/87  C. Royale          Added "Decode_Token" function.
  1888.  
  1889.       Diana_File_Non_Existent
  1890.         : exception;
  1891.  
  1892.       Source_File_Not_Open
  1893.         : exception;
  1894.  
  1895.       Illegal_Token
  1896.         : exception;
  1897.  
  1898.        --  .................................
  1899.        --  .                               .
  1900.        --  .    Obtain_Next_Token          .   SPEC
  1901.        --  .                               .
  1902.        --  .................................
  1903.  
  1904.       procedure Obtain_Next_Token
  1905.         (
  1906.           ...
  1907.               );
  1908.  
  1909.       ...
  1910.  
  1911.        --  ....................
  1912.        --  .                  .
  1913.        --  .    Decode_Token  .    SPEC
  1914.        --  .                  .
  1915.        --  ....................
  1916.  
  1917.       function Decode_Token
  1918.         (
  1919.           ...
  1920.               )
  1921.         return Parser_Types.TOKEN_VALUE_TYP;
  1922.  
  1923.      ...
  1924.     end Lexical_Analyzer;
  1925.  
  1926. 5.7.6.2  Example 7X2.
  1927.  
  1928.        --  ***************************
  1929.        --  *                         *
  1930.        --  *    Lexical Analyzer     *    BODY
  1931.        --  *                         *
  1932.        --  ***************************
  1933.  
  1934.     with Text_IO,
  1935.          File_Handler;
  1936.  
  1937.     package body Lexical_Analyzer is
  1938.  
  1939.   --  Notes
  1940.   --  The package "Lexical_Analyzer" will later be changed to:a task,
  1941.   --  so that the "Parser" task (now a package) can make an entry
  1942.   --  call to "Lexical_Analyzer" when it needs the next token.
  1943.   --
  1944.   --  Modifications
  1945.   --  6/14/85 Charity Royale Initial version of body.
  1946.   --  8/26/85 Charity Royale  Added "Decode_Token" function.
  1947.  
  1948.   --                          Added instantiation of "Enumeration_IO."
  1949.  
  1950.          --  ******************
  1951.          --  *                *
  1952.          --  *    Char_IO     *    SPEC
  1953.          --  *                *
  1954.          --  ******************
  1955.  
  1956.   package Char_IO is
  1957.     new Text_IO.Enumeration IO (Enum => Character);
  1958.  
  1959.   --  Purpose
  1960.   --  Used to read the input text file character by character.
  1961.   --
  1962.   --  Initialization Exceptions (none)
  1963.   --  Notes (none)
  1964.  
  1965.        --  ..................................
  1966.        --  .                                .
  1967.        --  .     Obtain_Next_Token          .   STUB
  1968.        --  .                                .
  1969.        --  ..................................
  1970.  
  1971.  
  1972.   procedure Obtain_Next_Token
  1973.     (
  1974.       ...
  1975.           ) is separate;
  1976.  
  1977.        -- ......................
  1978.        -- .                    .
  1979.        -- .    Decode_Token    .   STUB
  1980.        -- .                    .
  1981.        -- ......................
  1982.  
  1983.   function Decode_Token
  1984.     (
  1985.       ...
  1986.           )
  1987.     return Parser_Types.TOKEN_VALUE_TYP is separate;
  1988.     ...
  1989.  
  1990.     begin  -- Lexical_Analyzer
  1991.  
  1992.      ...
  1993.  
  1994.     exception
  1995.       when File_Handler.File_Error =>
  1996.         raise Diana_File_Non_Existent
  1997.  
  1998.     end Lexical_Analyzer;
  1999.  
  2000. 5.7.6.3  Example 7X3.
  2001.  
  2002.        --  *********************
  2003.        --  *                   *
  2004.        --  *       Disk        *      SPEC
  2005.        --  *                   *
  2006.        --  *********************
  2007.  
  2008.     generic
  2009.  
  2010.       type SPECIFIC_DATA_TYP is  -- The type of data to be
  2011.         ( <> );                  -- stored on disk
  2012.  
  2013.     package Disk is
  2014.  
  2015.   --  Purpose
  2016.   --  This package defines an abstract data type to simplify
  2017.   --  the I/O interface to disk files.
  2018.   --
  2019.   --  Initialization Exceptions (none)
  2020.   --  Notes (none)
  2021.   --  Modifications
  2022.   --  9/10/86  Ada Users Group    Initial version
  2023.  
  2024.       type FILE_TYP is private;
  2025.  
  2026.       End_Of_File
  2027.         :  exception;
  2028.  
  2029.       Open_Error
  2030.         :  exception;
  2031.  
  2032.       Mode_Error
  2033.         :  exception;
  2034.  
  2035.       subtype FILE_MODE is
  2036.         (IN_FILE, OUT_FILE);
  2037.  
  2038.        --  .....................
  2039.        --  .                   .
  2040.        --  .    Create         .   SPEC
  2041.        --  .                   .
  2042.        --  .....................
  2043.  
  2044. function Create
  2045.   ( Name  :  STRING;
  2046.     Mode  :  FILE_MODE := IN_FILE )
  2047.   return FILE_TYP;
  2048.  
  2049.   --  Purpose
  2050.   --  This function creates a FILE_TYP data object to
  2051.   --  represent the disk file with the given name and mode.
  2052.   --
  2053.   --  Exceptions (none)
  2054.   --  Notes
  2055.   --  This function does not actually open the file.
  2056.  
  2057.  
  2058.        --  .....................
  2059.        --  .                   .
  2060.        --  .       Close       .     SPEC
  2061.        --  .                   .
  2062.        --  .....................
  2063.  
  2064.    procedure Close
  2065.      ( Disk_File : in out FILE_TYP );
  2066.  
  2067.   --  Purpose
  2068.   --  This procedure closes a disk file if it is open.  If
  2069.   --  the file is already closed it has no effect.
  2070.   --
  2071.   --  Exceptions (none)
  2072.   --  Notes (none)
  2073.  
  2074.        --  ....................
  2075.        --  .                  .
  2076.        --  .      Read        .   SPEC
  2077.        --  .                  .
  2078.        --  ....................
  2079.  
  2080.    procedure Read
  2081.      ( Disk_File : in out FlLE_TYP;
  2082.        Data      : out    SPECIFIC_DATA_TYP );
  2083.  
  2084.   --  Purpose
  2085.   --  This procedure reads the next record from a file,
  2086.   --  opening the file if necessary.
  2087.   --
  2088.   --  Exceptions
  2089.   --  End_Of_File     - raised if no more elements can be
  2090.   --                    read from the file
  2091.   --  Open_Error      - if the file cannot be opened
  2092.   --  Mode_Error      - if the file mode is not IN FILE
  2093.   --
  2094.   --  Notes (none)
  2095.  
  2096.        --  ......................
  2097.        --  .                    .
  2098.        --  .      Write         .    SPEC
  2099.        --  .                    .
  2100.        --  ......................
  2101.  
  2102.        procedure Write
  2103.          ( Disk_File : in out FILE_TYP;
  2104.            Data      : in     SPECIFIC_DATA_TYP );
  2105.  
  2106.   --  Purpose
  2107.   --  This function writes a record to a file,
  2108.   --  opening the file if necessary.
  2109.   --
  2110.   --  Exceptions
  2111.   --  Open_Error         - if the file cannot be opened
  2112.   --  Mode_Error        - if the file mode is not OUT_FILE
  2113.   --
  2114.   --  Notes (none)
  2115.  
  2116.   private   -- Disk
  2117.  
  2118.        --  *********************
  2119.        --  *                   *
  2120.        --  *     Disk_IO       *     SPEC
  2121.        --  *                   *
  2122.        --  ********************* package Disk_IO is
  2123.  
  2124.   new Sequential_IO (SPECIFIC_DATA_TYP);
  2125.  
  2126.   --  Purpose --  This package provides the basis for the representation
  2127.   --  of disk files.
  2128.   --
  2129.   --  Initialization Exceptions (none)
  2130.   --  Notes (none)
  2131.  
  2132.     File_Name_Length
  2133.       : constant := 40;
  2134.  
  2135.     type FILE_TYP is
  2136.       record
  2137.         File_Name : STRING (1..File_Name_Length) := (others => ' ');
  2138.         File      : Disk_IO.FILE_TYP;
  2139.         Mode      : FILE_MODE                    := Disk_IO.IN_FILE;
  2140.       end record;
  2141.   end Disk;
  2142.  
  2143. 5.8  Visibility.
  2144.  
  2145.  
  2146. 5.8.1  Scope of identifiers.  The scope of identifiers should not extend
  2147. further than necessary.  Where a scope is extended by "with" clauses, these
  2148. clauses should cover as small a region of text as possible.
  2149.  
  2150. For example, "with" clauses should be placed only on the subunits that really
  2151. need them, not on their parents.  This promotes information hiding and reduces
  2152. coupling.  It can also result in faster recompilation (due to the dependency
  2153. rules).
  2154.  
  2155. 5.8.2  The package STANDARD and WITH clauses.  The package STANDARD should
  2156. not be named in a "with" clause.
  2157.  
  2158. 5.8.3  The use clause.  The "use" clause should be employed only in a limited
  2159. application.  It detracts from the readability of the program by allowing
  2160. the "expanded" name to be shorten (not having to specify the "prefix", not
  2161. having to use the dot notation).  Thus, the understandability of the program
  2162. may be affected.  Another detraction, there is an outside possibility it may
  2163. introduce a name clash.
  2164.  
  2165. 5.8.4  Renaming declarations.  Usually renaming causes more problems than it
  2166. is worth; so again, use it in a limited fashion, if at all.
  2167.  
  2168.     a.  For a name with a large number of package qualifications, a renaming
  2169. declaration may be used to define a new shorter name.  The new identifier
  2170. should still reflect the complete meaning of the full name.
  2171.  
  2172.     b.  For a function which can be appropriately represented by an operator
  2173. symbol name, a renaming declaration may be used to give it such a name.
  2174. However, notice that a renaming declaration may have some appropriateness
  2175. for achieving direct visibility, e.g.
  2176.  
  2177. A Matrix_ Multiply function could be renamed "*".
  2178.  
  2179. 5.8.5  Redefinition.
  2180.  
  2181.     a.  It is extremely poor programming practice to redefine or rename items
  2182. from the package STANDARD.
  2183.  
  2184.     b.  Redefinition of an identifier in different declarations should be
  2185. avoided.
  2186.  
  2187. 5.9  Tasks.
  2188.  
  2189.  
  2190. 5.9.1  Use of tasks.  A task should fulfill one or more of the following:
  2191.  
  2192.     a.  Model a concurrent abstract entity appropriate to the problem domain.
  2193.  
  2194.     b.  Serve as an aceess-controlling or synchronizing agent for other tasks,
  2195. or otherwise act as an interface between asynchronous tasks.
  2196.  
  2197.     c.  Serve as an interface to asynchronous entities external to the program
  2198. (e.g., asynchronous I/O, devices, interrupts, etc.).
  2199.  
  2200.     d.  Define concurrent algorithms for faster execution on multiprocessor
  2201. architectures.
  2202.  
  2203.     e.  Perform an activity which must wait a specified time for an event or
  2204. have a specific priority.
  2205.  
  2206. Just as for packages (paragraph 5.7.1) it is best to have tasks which model
  2207. problem domain entities.  However, in the case of tasks it is also necessary
  2208. to have some tasks which provide interfaces between other tasks and which
  2209. handle the other issues of concurrency and parallelism mentioned above.  The
  2210. program should generally be structured, however, around the tasks which
  2211. represent problem-domain entities.
  2212.  
  2213. 5.9.2  Nesting of tasks.
  2214.  
  2215.     a.  Tasks should generally not be nested within tasks or subprograms,
  2216. except for the main procedure.
  2217.  
  2218. Note that a subprogram containing a task cannot return until the task has
  2219. terminated.
  2220.  
  2221.     b.  Nested task bodies should be separate subunits, unless they are quite
  2222. small.
  2223.  
  2224. 5.9.3  Visibility of tasks.
  2225.  
  2226.     a.  When only certain entries of a task are intended to be called by
  2227. program components outside an enclosing package, it is generally preferable to
  2228. hide the task specification in the package body, introducing package
  2229. procedures which in turn call the actual entries.
  2230.  
  2231.     b.  This helps to promote information hiding and strengthens the
  2232. abstraction of the enclosing package (see paragraph 5.7.2.d).  It also hides
  2233. the use of tasking within the package.  Note, however, that special care must
  2234. be taken if the task entries are to be called using conditional or timed entry
  2235. calls.  In this case either the outer package must provide special procedures
  2236. or procedure parameters or this guideline should not be followed.
  2237.  
  2238. 5.9.4  Task types.
  2239.  
  2240.     a.  A task type should be used only when multiple instances of that type
  2241. are required.  Otherwise a directly named task should be used.
  2242.  
  2243.     b.  Identical tasks should be derived from a common task type.
  2244.  
  2245.     c.  Static task structures should be used whenever they are sufficient.
  2246. Access types to task type should be used only when it is essential to create
  2247. and destroy tasks dynamically, or to be able to change the names with which
  2248. they are associated.
  2249.  
  2250. 5.9.5  Task termination.  Nesting of tasks within other tasks should be
  2251. avoided.  If tasks must be nested, they should be forced to terminate when
  2252. they are suppose to by causing them to reach their end statement.  If a task
  2253. is a "active" task, this is done by having the main loop as a "while" loop.
  2254. If the task is "passive", there should be an entry which causes the main loop
  2255. to be exited.
  2256.  
  2257. 5.9.6  Entries and accept statements.
  2258.  
  2259.     a.  Only those actions should be included in the "accept" statement which
  2260. must be completed before the calling task is released from its waiting state.
  2261.  
  2262.     b.  Conditional entry calls should be used sparingly to avoid unnecessary
  2263. busy waiting.
  2264.  
  2265. 5.9.7  Delay statement.
  2266.  
  2267.     a.  A "delay" statement should be used whenever a task must wait for some
  2268. known duration.  A "busy wait" loop should never be used for this purpose.
  2269.  
  2270. It is important to remember that "delay t" provides a delay of at least t
  2271. seconds, but possibly more.  A program should not rely on any upper bound for
  2272. this delay, especially when tasks are used (since tasks must compete for CPU
  2273. time).
  2274.  
  2275.   The following example is only one of many techniques to alleviate this
  2276. problem in a periodic activity:
  2277.  
  2278.     ...
  2279.     Next_Time := Calendar.Clock + Required_ Period;
  2280.  
  2281.    Periodic_Activity:
  2282.    while Still_Time.loop
  2283.       -- Perform activity
  2284.       ...
  2285.       -- Correct for delay statement incertitude
  2286.       Period := Next_Time - Calendar.Clock;
  2287.  
  2288.       if Period < 0.0 then           -- Processing was too slow
  2289.         Next_Time := Calendar.Clock  -- Avoid cumulative effect
  2290.       end if;
  2291.       Next_Time := Next_Time + Required_Period;
  2292.       delay Period;
  2293.     end loop Periodic_Activity;
  2294.  
  2295.     b.  The "delay" statement should normally only be used to manage
  2296. interaction with some external process which works in real time, or to create
  2297. a task which behaves in a well-defined manner in real time.
  2298.  
  2299. 5.9.8  Task synchronization.  Knowledge of the execution pattern of tasks
  2300. (e.g., fixed, known time pattern, etc.) should not be used to avoid the use of
  2301. explicit task synchronization.
  2302.  
  2303. 5.9.9  Priorities.
  2304.  
  2305.     a.  Only a small number of priority levels should be used.  The priority
  2306. levels used should be spread over the range made available to type PRIORITY in
  2307. the implementation.  Names should be given to the priority levels by declaring
  2308. constants of predefined type PRIORITY and grouping these declarations into a
  2309. single package.
  2310.  
  2311. Using only a small number of priority levels makes the interaction of the
  2312. various prioritized tasks easier to understand.  On the other hand, spreading
  2313. the levels across the available range allows easy insertion of a new level
  2314. between existing levels if this later becomes necessary.  As with other
  2315. literal numbers, the use of names is more readable than the use of the
  2316. literals.
  2317. Further, for priorities, the allowable range of levels is implementation
  2318. dependent.  Naming priority levels by constant declarations grouped into a
  2319. single package restricts the implementation dependency to that package.  For
  2320. example:
  2321.  
  2322.   with System;
  2323.   package Priority_Levels is
  2324.       Lowest_Priority
  2325.         : constant System.PRIORITY := System.PRIORITY'first;
  2326.       Highest_Priority
  2327.         : constant System.PRIORITY := System.PRIORITY'last;
  2328.       Median
  2329.         : constant                 := Highest_Priority - Lowest_Priority + 1;
  2330.       Average
  2331.         : constant System.PRIORITY := Lowest_Priority + (Median / 2);
  2332.       Idle
  2333.         : constant System.PRIORITY := Lowest_Priority;
  2334.       Background
  2335.         : constant System.PRIORITY := Lowest_Priority + (Median / 5);
  2336.       User
  2337.         : constant System.PRIORITY := Lowest_Priority + (2 * Median / 5);
  2338.       Foreground
  2339.         : constant System.PRIORITY := Lowest_Priority + (4 * Median / 5);
  2340.     end Priority_Levels;
  2341.  
  2342.     b.  For any group of related tasks, such as those declared within the same
  2343. program unit, priorities should be specified either for all, or for none of
  2344. them.
  2345.  
  2346. This avoids confusion about the scheduling of tasks with undefined priorities.
  2347.  
  2348. 5.9.10  Abort statements.  Abortion of tasks should generally be avoided.
  2349.  
  2350. Aborting a task can produce unpredictable results.  In particular, do not
  2351. assume anything about the moment at which an aborted task becomes terminated.
  2352. The "abort" statement should generally be used only in case of unrecoverable
  2353. failure.
  2354.  
  2355. 5.9.11  Shared variables.
  2356.  
  2357.     a.  Tasks should not directly share variables unless only one of them can
  2358. possibly be running at any one time.
  2359.  
  2360.     b.  Any task which uses shared variables should identify in its
  2361. documentary comments all the shared variables that it uses.
  2362.  
  2363. 5.9.12  Local exception handling.  To allow the handling of local exceptions
  2364. without task termination, a task should generally have a block statement with
  2365. an exception handler coded within its main loop.
  2366.  
  2367.     begin  -- Some Task
  2368.  
  2369.       Main_Loop:
  2370.       loop
  2371.  
  2372.         Local:
  2373.         begin
  2374.           -- Task code
  2375.           ...
  2376.         exception  -- Local
  2377.           -- handle local exceptions ...
  2378.         end Local;
  2379.  
  2380.       end Main_Loop;
  2381.  
  2382.     exception
  2383.       -- handle fatal exceptions ...
  2384.  
  2385.     end Some_Task;
  2386.  
  2387. 5.9.13  Formatting of tasks.
  2388.  
  2389. 5.9.13.1  Task and entry names.
  2390.  
  2391.     a.  A task name should be a noun phrase describing the task function or
  2392. abstract entity modeled by the task.
  2393.  
  2394.     Sensor_Interface
  2395.     Status_Monitor
  2396.     Event_Handler
  2397.     Message_Buffer
  2398.  
  2399.  b.  Entry names should follow the same guidelines as for subprogram names
  2400. (see paragraph 5.6.6.1).
  2401.  
  2402. 5.9.13.2  Task and entry headers.  Each task or task type specification or
  2403. body and each entry specification should be preceded by a header comment block
  2404. containing at least the unit name and the indication SPEC, BODY or STUB.
  2405.  
  2406.        --  **********************
  2407.        --  *                    *
  2408.        --  *       Buffer       *     SPEC
  2409.        --  *                    *
  2410.        --  **********************
  2411.  
  2412.      task Buffer is
  2413.  
  2414.  
  2415.        --  ....................
  2416.        --  .                  .
  2417.        --  .      Read        .   SPEC
  2418.        --  .                  .
  2419.        --  ....................
  2420.  
  2421.        entry Read ( Output : out Character );
  2422.  
  2423.  5.9.13.3  Task specifications.
  2424.  
  2425.      a.  Task specifications should have the following format:
  2426.  
  2427.      task <task identifier> is
  2428.  
  2429.      --   <documentary comments>
  2430.  
  2431.        <declaration>
  2432.        <declaration>
  2433.  
  2434.      end <task identifier>;
  2435.  
  2436. Guidelines for <documentary comments> should be AT LEAST as rigorous as those
  2437. for a subprogram declaration (see paragraph 5.6.6.3), except for the
  2438. "Exceptions" section.
  2439.  
  2440. NOTE: The <task identifier> should always be repeated at the "end" of the
  2441. task specification.
  2442.  
  2443.     b.  A task type specification should be formatted the same as a task
  2444. specification, with the exception of including "task type" in the header.
  2445.     c.  Entry declarations should have the following format:
  2446.  
  2447.     entry <entry identifier> (<family range>)
  2448.       (  <parameter specification>;
  2449.          <parameter specification>  );
  2450.  
  2451.     --  <documentary comments>
  2452.  
  2453. Each <parameter specification> should be formatted like an object declaration
  2454. (see paragraph 5.3.8.4).  Guidelines for <documentary comments> should be AT
  2455. LEAST as rigorous as those for a subprogram declaration (see
  2456. paragraph 5.6.6.3).
  2457.  
  2458.     d.  Parameter mode indications should always be used in entry
  2459. declarations.
  2460.  
  2461.     e.  In a declarative part, all task specifications should appear before
  2462. any task or package bodies.
  2463.  
  2464. 5.9.13.4  Task bodies and stubs.
  2465.  
  2466.     a.  Task bodies should have the following format:
  2467.  
  2468.     separate (<parent>)
  2469.     task body <task identifier> is
  2470.  
  2471.     --  <documentary comments>
  2472.  
  2473.       <declaration>
  2474.       <declaration>
  2475.  
  2476.     begin  --  <task identifier>
  2477.  
  2478.       <statement>
  2479.       <statement>
  2480.  
  2481.     exception
  2482.       when <exceptions> =>
  2483.         <statement>
  2484.  
  2485.     end <task identifier>;
  2486.  
  2487.     b.  Guidelines for <documentary comments> should be AT LEAST as rigorous
  2488. as those for a subprogram declaration (see paragraph 5.6.6.3).
  2489.  
  2490. NOTE: The <task identifier> should always be repeated at the "end" of the
  2491. task body.
  2492.  
  2493.     c.  Task stubs should have the following format:
  2494.  
  2495.     task body <task identifier> is separate;
  2496.  
  2497. 5.9.13.5  Accept statements.
  2498.  
  2499.  
  2500.     a.  "Accept" statements should have one of the following formats:
  2501.     accept <entry identifier> (<entry index>);
  2502.  
  2503.     accept <entry identifier> (<entry index>)
  2504.       (  <parameter specification>;
  2505.          <parameter specification> )
  2506.     do
  2507.       <statement>
  2508.       <statement>
  2509.     end <entry identifier>;
  2510.  
  2511. Each <parameter specification> should be formatted like an object declaration
  2512. (see paragraph 5.3.8.4).  Note that the <entry identifier> should always be
  2513. repeated at the "end" of the "accept" (if there is an "end").
  2514.  
  2515.     b.  Parameter mode indications should always be used in accept statements.
  2516.  
  2517.  
  2518. 5.9.13.6  Select statements.
  2519.  
  2520.     a.  Selective wait statements should have the following format:
  2521.  
  2522.     select
  2523.       <statement>
  2524.       <statement>
  2525.     or
  2526.       <statement>
  2527.       <statement>
  2528.     or
  2529.       when <condition> =>
  2530.         <statement>
  2531.         <statement>
  2532.     end select;
  2533.  
  2534. This format is consistent with the indentation style of other statements.  In
  2535. addition, the added level of indentation especially highlights guarded
  2536. sections of code.
  2537.  
  2538.     b.  Conditional and timed entry calls should have the following format:
  2539.  
  2540.     select
  2541.       <entry call>
  2542.       <statement>
  2543.     else
  2544.       <statement>
  2545.       <statement>
  2546.     end select;
  2547.  
  2548. 5.9.13.7  Pragma priority. The priority pragma should appear in task
  2549. specification before any entry declarations, and in the main program before
  2550. any declarations.
  2551.  
  2552. 5.9.14  Examples for tasks.
  2553.  
  2554.  
  2555. 5.9.14.1  Example 9X1.
  2556.  
  2557.        --  **********************
  2558.        --  *                    *
  2559.        --  *       Buffer       *    SPEC
  2560.        --  *                    *
  2561.        --  **********************
  2562.  
  2563.     task Buffer is
  2564.  
  2565.   --  Purpose
  2566.   --  This task provides a character buffer to smooth variations
  2567.   --  between the speed of output of a producing task and the speed
  2568.   --  of input of a consuming task.
  2569.   --
  2570.   --  Exceptions (none)
  2571.   --  Notes (none)
  2572.  
  2573.        --  .....................
  2574.        --  .                   .
  2575.        --  .      Read         .    SPEC
  2576.        --  .                   .
  2577.        --  .....................
  2578.  
  2579.       entry Read ( Output     : out Character );
  2580.  
  2581.   --  Purpose
  2582.   --  This entry reads a character from the buffer.
  2583.   --  If the buffer is empty, the entry will wait
  2584.   --  until a character is written into the buffer.
  2585.   --
  2586.   --  Exceptions (none)
  2587.   --  Notes (none)
  2588.  
  2589.        --  .....................
  2590.        --  .                   .
  2591.        --  .      Write        .    SPEC
  2592.        --  .                   .
  2593.        --  .....................
  2594.  
  2595.       entry Write ( Input   : in Character );
  2596.  
  2597.   --  Purpose
  2598.   --  This entry writes a character into the buffer.
  2599.   --  If the buffer is full the entry will wait
  2600.   --  until a character is read from the buffer.
  2601.   --
  2602.   --  Exceptions (none)
  2603.   --  Notes (none)
  2604.  
  2605.     end Buffer;
  2606.  
  2607. 5.9.14.2  Example 9X2.
  2608.  
  2609.        --  **********************
  2610.        --  *                    *
  2611.        --  *      Buffer        *    BODY
  2612.        --  *                    *
  2613.        --  **********************
  2614.  
  2615.     separate (Buffer Package)
  2616.     task body Buffer is
  2617.  
  2618.    --  Notes
  2619.    --  This task contains an internal pool of characters processed
  2620.    --  in a round-robin fashion.
  2621.    --
  2622.    --  Modifications
  2623.    --  7/2/86  Fred Blah    Initial version.
  2624.  
  2625.       Pool_Size
  2626.         : constant                   := 100;
  2627.       subtype POOL_RANGE is
  2628.         INTEGER range 1..Pool_Size;
  2629.       type POOL_TYP is
  2630.         array (POOL_RANGE) of CHARACTER;
  2631.       Pool
  2632.         : POOL_TYP;
  2633.       Count                                   -- The number of characters in
  2634.         : INTEGER range 0..Pool_Size := 0;    -- the pool.
  2635.       In_Index                                -- The space for the next input
  2636.         : POOL_RANGE                 := 1;    -- character.
  2637.       Out_Index                               -- The space for the next output
  2638.         : POOL_RANGE                 := 1;    -- character.
  2639.  
  2640.      begin   -- Buffer
  2641.  
  2642.        Pool_Loop:
  2643.        loop
  2644.          select
  2645.            when Count < Pool_Size =>
  2646.              accept Write ( Input  : in Character ) do
  2647.                Pool(In_Index) := Input;
  2648.              end write;
  2649.              In_Index := In_Index mod Pool_Size + 1;
  2650.              Count := Count + 1;
  2651.          or
  2652.            when Count > 0 =>
  2653.              accept Read ( Output : out Character) do
  2654.                Output := Pool(Out_Index);
  2655.              end Read;
  2656.              Out_Index := Out_Index mod Pool_Size + 1;
  2657.              Count := Count - 1;
  2658.          or
  2659.            terminate;
  2660.          end select;
  2661.  
  2662.        end loop Pool_Loop;
  2663.  
  2664.      end Buffer;
  2665.  
  2666. 5.9.14.3  Example 9X3.
  2667.  
  2668.        --  ...................
  2669.        --  .                 .
  2670.        --  .   Shellsort     .      BODY
  2671.        --  .                 .
  2672.        --  ...................
  2673.  
  2674.     procedure Shellsort
  2675.       ( List            : in out ITEM_LIST;     -- to be sorted in place.
  2676.         Number_Of_Items : in     NATURAL );
  2677.  
  2678.   --  Purpose
  2679.   --  This is a basic integer sorting routine.
  2680.  
  2681.   --  Notes
  2682.   --  This sorting procedure implements the Shell sort by
  2683.   --  separating the n-sorts into multiple Ada tasks.
  2684.   --  This algorithm is designed for parallel processing
  2685.   --  of the tasks and is not an efficient method on a
  2686.   --  single processor.  The process works on an one
  2687.   --  dimensional array called ITEM_LIST.
  2688.   --
  2689.   --  Modifications
  2690.   --  9/5/86  A. Shell           Initial version
  2691.  
  2692.   Increment                   -- Increment of an n-sort
  2693.     : NATURAL;
  2694.  
  2695.   Number_of_Sorts             -- Number of parallel sorts
  2696.     : NATURAL;                -- for a single pass
  2697.  
  2698.   Number_Of_Tasks
  2699.     : NATURAL;
  2700.  
  2701.        --  ********************
  2702.        --  *                  *
  2703.        --  *   SORTER TASK    *      SPEC
  2704.        --  *                  *
  2705.        --  ********************
  2706.  
  2707.   task type SORTER_TASK is
  2708.  
  2709.   --  Purpose
  2710.   --  Tasks of this type perform the n-sort for the Shell sort.
  2711.   --
  2712.   --  Notes
  2713.   --  A SORTER_TASK terminates itself when it is no longer
  2714.   --  needed for the sort.
  2715.  
  2716.        --  ......................
  2717.        --  .                    .
  2718.        --  .     Sort           .   SPEC
  2719.        --  .                    .
  2720.        --  ......................
  2721.  
  2722.   entry Sort
  2723.     ( First : in INTEGER;
  2724.       Step  : in NATURAL );
  2725.    --  Purpose
  2726.    --  This entry signals a sorter task to perform a new
  2727.    --  n-sort.  Elements are sorted in place in List,
  2728.    --  starting with the element at index First and
  2729.    --  including subsequent elements at the indicated Step.
  2730.    --
  2731.    --  Exceptions (none)
  2732.    --  Notes (none)
  2733.  
  2734.   end SORTER_TASK;
  2735.  
  2736.        --  *********************
  2737.        --  *                   *
  2738.        --  *   SORTER_TASK     *      STUB
  2739.        --  *                   *
  2740.        --  *********************
  2741.  
  2742.   task body SORTER_TASK is separate;
  2743.  
  2744.   type SORTER_ARRAY is
  2745.     array (INTEGER range <>) of SORTER_TASK;
  2746.  
  2747. begin   -- Shellsort
  2748.  
  2749.   if Number_Of_Items < 2 then
  2750.     return;
  2751.   end if;
  2752.  
  2753.   -- Determine the first n-sort increment.
  2754.   Increment := 1;
  2755.  
  2756.   while Increment < Number_Of_Items  loop
  2757.     Increment := (3 * Increment) + 1;
  2758.   end loop;
  2759.  
  2760.   Increment := Increment / 3;
  2761.   if Increment < 1 then
  2762.     Increment := 1;
  2763.   end if;
  2764.  
  2765.   --  Determine the number of tasks required to perform
  2766.   -- the sort.
  2767.  
  2768.   if Number_Of_Items / Increment = 1 then
  2769.     Number_of_Sorts := Number Of Items mod Increment;
  2770.     if Increment / 3 > Number Of Sorts then
  2771.       Number_Of_Tasks := Increment / 3;
  2772.     else
  2773.       Number_Of_Tasks := Number_Of_Sorts;
  2774.     end if;
  2775.   else
  2776.     Number_Of_Sorts := Increment;
  2777.     Number_of_Tasks := Number_Of_Sorts;
  2778.   end if;
  2779.  
  2780.   -- Perform the sort
  2781.  
  2782.   Task_Block:
  2783.   declare
  2784.     Sort_List
  2785.       : SORTER_ARRAY (1 .. Number_Of_Tasks);
  2786.   begin  -- Task_Block
  2787.  
  2788.     Incrementation:
  2789.     while Increment > 0 loop
  2790.  
  2791.       Sort_Work:
  2792.       for K in 1 .. Number_Of_Sorts loop
  2793.         Sort_List(K).Sort
  2794.           ( First    => List'first + K - 1'
  2795.             Step     => Increment );
  2796.       end loop Sort_Work;
  2797.  
  2798.       Increment := Increment / 3;
  2799.       Number_of_Sorts := Increment;
  2800.     end loop Incrementation;
  2801.  
  2802.   end Task_Block;
  2803.  
  2804. end Shellsort;
  2805.  
  2806. 5.9.14.4  Example 9X4.
  2807.  
  2808.        --  *********************
  2809.        --  *                   *
  2810.        --  *    SORTER_TASK    *    SUBUNIT
  2811.        --  *                   *
  2812.        --  *********************
  2813.  
  2814.     separate (Shellsort)
  2815.     task body SORTER_TASK is
  2816.  
  2817.   --  Notes
  2818.   --  This task body implements a task type.
  2819.   --
  2820.   --  Modifications
  2821.   --  9/5/86    A. Shell        Initial version
  2822.  
  2823.   -- Global variables
  2824.   -- List                 -- An array of all items to be
  2825.                              sorted by Shellsort.
  2826.   -- Number_Of_Items      -- The number of items in the list.
  2827.  
  2828.   Start        : INTEGER;
  2829.   Increment    : NATURAL;
  2830.  
  2831.   A            : INTEGER;
  2832.   B            : INTEGER;
  2833.   First_B      : INTEGER;
  2834.  
  2835.   Temp         : INTEGER;
  2836.  
  2837.    begin   -- SORTER_TASK
  2838.  
  2839.   Main_Loop:
  2840.   loop
  2841.  
  2842.     accept Sort
  2843.       ( First     : in INTEGER;
  2844.         Step      : in NATURAL )
  2845.     do
  2846.       Start := First;
  2847.       Increment := Step;
  2848.     end Sort;
  2849.  
  2850.     First_B := Start + Increment;
  2851.  
  2852.     Determine_Criteria:
  2853.     while First_B <= List'first + Number_Of_Items - 1 loop
  2854.       B := First_B;
  2855.       A := B - Increment;
  2856.  
  2857.       Find_Position:
  2858.       while A >= Start loop exit when not (List(A) > List(B));
  2859.         Temp := List(A);
  2860.         List(A) := List(B);
  2861.         List(B) := Temp;
  2862.         B := A;
  2863.         A := B - Increment;
  2864.       end loop Find_Position;
  2865.  
  2866.       First_B := First_B + Increment;
  2867.  
  2868.     end loop Determine_Criteria;
  2869.  
  2870.     -- Terminate if task is not needed for n-sort
  2871.     exit when (Increment / 3) < Start - List'first + 1;
  2872.   end loop Main_Loop;
  2873.  
  2874. end SORTER_TASK;
  2875.  
  2876. 5.10  Program structure and compilation issues.
  2877.  
  2878.  
  2879. 5.10.1  Library units.   Library units are divided into two categories,
  2880. subprograms and packages.  Library subprograms define one entity, whereas
  2881. packages provide services which define more than on entity.  Some of the
  2882. primary uses are:
  2883.  
  2884.         a. To allow configuration control of the high level functional
  2885. subsystems of a program.
  2886.  
  2887.         b. For general purposes, reusable program units.
  2888.  
  2889. 5.10.2  WITH clauses.
  2890.  
  2891.     a.  No unit should have a "with" clause for a unit it does not need to see
  2892.  
  2893. directly.
  2894.  
  2895.     b.  If only a small part of a given unit needs access to a library unit,
  2896. then it should generally appear as a subunit and have its own "with" clause
  2897. for that library unit (see paragraph 5.8.1).
  2898.  
  2899. NOTE:  Understanding the use of the "with" clause is important.  Where the
  2900. "with" is interpreted, based on the compiler, can cause recompilation
  2901. problems by hiding names.
  2902.  
  2903. 5.10.3  Program unit dependencies.
  2904.  
  2905.     a.  Excessive dependencies between compilation units should be avoided,
  2906. especially the use of complicated networks of "with" clauses.
  2907.  
  2908.     b.  It is preferable to limit program unit dependencies to a logical tree
  2909. structure whenever possible.  In this instance, the preferred tree stucture
  2910. would be where a parent can have multiple children; however, every child has
  2911. only one parent.  Any program that creates a dependency of multiple parents
  2912. to multiple children should be evaluated for redesign.
  2913.  
  2914. 5.11  Exceptions.
  2915.  
  2916.  
  2917. 5.11.1  Exception propagation.
  2918.  
  2919.     a. Exceptions propagated by a program unit should be considered part of
  2920. the abstraction or function represented by that unit.  Therefore, it should
  2921. generally only propagate exceptions which are appropriate to that level of
  2922. abstraction.  If necessary, an exception which cannot be handled by a unit at
  2923. one level of abstraction should be converted into an exception which can be
  2924. explicitly recognized by the next higher level.
  2925.  
  2926. For example, a Stack package should provide a Stack_Full exception instead of
  2927. propagating a Constraint_Error.  Similarly, a Matrix_lnverse function should
  2928. raise a Matrix_is_Singular exception rather than propagating Numeric_Error.
  2929.  
  2930.     b.  Exceptions should not be allowed to propagate outside their own scope.
  2931. An exception may be allowed to propagate to any point where it can be named in
  2932. an exception handler.  Note that this includes the case where an exception is
  2933. defined in a package specification and has its scope "expanded" by a "with"
  2934. clause.  What must be avoided are cases such as the following:
  2935.  
  2936.     procedure Raise_Exception is
  2937.       Hidden_Exception  : exception;
  2938.     begin
  2939.       raise Hidden_Exception;
  2940.     end Raise_Exception;
  2941.  
  2942.   begin
  2943.     Raise_Exception;
  2944.     -- "Hidden_Exception" CANNOT be named at this point
  2945.  
  2946. 5.11.2  Use of exceptions.
  2947.  
  2948.     a.  An exception should be used sparingly.  If used, extensive and clear
  2949. comments should be included.  Possible reasons for exceptions are:
  2950.  
  2951.         (1) It reports an irregular event which is outside the normal
  2952. operation of a program unit or is in some sense an error.
  2953.  
  2954.         (2) It is used where it can be argued that it is safer (more
  2955. defensive) than the alternative, in particular to guard against omissions of
  2956. error checking code for especially harmful errors.
  2957.  
  2958.         (3) It reports an event for which it is inconvenient or unnatural to
  2959. test at the point of cause/occurrence and thus use of the exception enhances
  2960. readability. Exceptions declared in package specifications are really part of
  2961. the abstraction defined by that package.  Therefore their use should be
  2962. integral  to the design of the package (see paragraph 5.10.1).
  2963.  
  2964. Also, note that the predefined exceptions should be used with care.  Due to
  2965. allowable implementation differences, they should not be relied upon to
  2966. indicate particular circumstances.
  2967.  
  2968.     b.  Exceptions should not be used as means of returning normal state
  2969. information.
  2970.  
  2971. For example, a Stack package may have Stack Full and Stack Empty exceptions
  2972. which are raised by its Push and Pop subprograms.  However, these subprograms
  2973. should not be used solely to raise exceptions to test if the appropriate
  2974. conditions are true.  Instead, the package should provide BOOLEAN functions
  2975. such as Full and Empty to test for these state conditions.
  2976.  
  2977. 5.11.3  Exception handlers.
  2978.  
  2979.     a.  The exception handler choice "others" should be used only if it is
  2980. necessary to ensure that no UNANTICIPATED exception can be propagated or if
  2981. some special action must be taken before propagation.
  2982.  
  2983. For example, important tasks should generally have an "others" clause in a
  2984. local exception handler (see paragraph 5.9.12) to prevent them from
  2985. terminating due to unanticipated exceptions.  However, in the case when it can
  2986. be expected that a certain exception may sometimes occur, then that exception
  2987. should always be explicitly named in the exception handler.
  2988.  
  2989.     b.  Recursion should not be used within an exception handler.
  2990.  
  2991.     c.  Exception handlers on block statements should be used sparingly. One
  2992. of the advantages of using exceptions is that it separates the error handling
  2993. code from the more often executed normal processing code.  Excessive use of
  2994. exception handlers in block statements can defeat this advantage.
  2995.  
  2996. 5.11.4  Raise statements.
  2997.  
  2998.     a.  Exceptions declared in the specification of a package which represents
  2999. a problem domain entity should not be raised outside that package.
  3000.  
  3001. Exceptions declared in a package specification should be considered part of
  3002. the abstraction defined by the package.  These exceptions provide special
  3003. "signals" from the package operations, and should thus not be raised outside
  3004. of the package.
  3005.  
  3006.     b.  Exceptions raised within a.task should always-be handled within the
  3007. task.
  3008.  
  3009. NOTE: In the case of an exception raised during a rendezvous the exception
  3010. will also be propagated back to the point of the entry call.
  3011.  
  3012.     c.  The predefined exceptions should generally not be explicitly raised.
  3013.  
  3014. 5.11.5  Suppressing checks.  Checks should not be suppressed except for
  3015. essential efficiency or timing reasons in thoroughly tested program units.
  3016.  
  3017. 5.11.6  Exception declarations.  Exception declarations should re formatted
  3018. like object declarations, paragraph 5.3.8.4.
  3019.  
  3020. 5.11.7  Examples for exceptions.  See examples 5.5.9.4, 5.6.7.5, 5.7.6.2,
  3021. and 5.14.5.2.
  3022.  
  3023. 5.12  Generic units.
  3024.  
  3025.  
  3026. 5.12.1  Use of generic units.
  3027.  
  3028.     a.  Generics should not be used in situations in which normal programming
  3029. constructs are equivalent.
  3030.  
  3031.     b.  A generic program unit should fulfill one or more of the following:
  3032.  
  3033.         (1) Provide logically equivalent operations on objects of different
  3034. type.
  3035.  
  3036.         (2)  Parameterize a program unit by a subprogram value.
  3037.  
  3038.         (3) Provide a data abstraction required at many points in a program,
  3039. even if no parameterization is required.
  3040.  
  3041.         (4) Provide parameters which are particularly appropriate to be fixed
  3042. at declaration or elaboration time.
  3043.  
  3044.         (5) Reduce coupling by controlling visibility.
  3045.  
  3046.     c. Functions should be made generic whenever possible to facilitate and
  3047. increase reusability.
  3048.  
  3049. 5.12.2  Generic library units.  Generic units should generally be library
  3050. units.
  3051.  
  3052. 5.12.3  Generic instantiation.
  3053.  
  3054.     a.  The most commonly used generic instantiations should generally be
  3055. placed in library units.
  3056.  
  3057.     b.  Generic instantiations should be used cautiously within generic units.
  3058.  
  3059. NOTE:  Information presented in some cases fall into the realm of guidelines
  3060. to compensate for compiler and/or run-time deficiencies.  Sub-subparagraph
  3061. b is an example.
  3062.  
  3063. 5.12.4  Generic formal subprograms.
  3064.  
  3065.     a.  The actual subprograms associated with the formal subprogram
  3066. parameters of a generic unit should be consistent with the conceptual meanings
  3067. of the formal parameters (e.g., only functions which are conceptually "adding
  3068. operations" should be associated with a formal parameter named "plus").
  3069.  
  3070.     b.  Operator symbol function generic parameters should generally be
  3071. provided with a box default body ("is <>").
  3072.  
  3073.     with function "<"
  3074.       ( X : ITEM;
  3075.         Y : ITEM )
  3076.       return BOOLEAN is <>;
  3077.  
  3078. 5.12.5  Use of attributes.
  3079.  
  3080.     In writing generic bodies, attributes should be used as much as possible
  3081. to generalize the code produced.
  3082.  
  3083. 5.12.6  Formatting of generic units.
  3084.  
  3085. 5.12.6.1  Generic declarations.
  3086.  
  3087.     a.  Generic declarations should have the following format:
  3088.  
  3089.     generic
  3090.       <declaration>
  3091.       <declaration>
  3092.     <program unit specification>;
  3093.  
  3094.     --  <documentary comments>.
  3095.  
  3096. Each <declaration> should be formatted like its non-formal counterpart (see
  3097. paragraphs 5.3.8.3 and 5.3.8.4), except for formal subprograms which should be
  3098. formatted as in b below.  The <program unit specification> should be formatted
  3099. as for non-generic units (see paragraphs 5.6.6.3 and 5.7.5.3).
  3100.  
  3101.     b.  A generic formal parameter subprogram declaration should have one of
  3102. the following formats:
  3103.  
  3104.     with <subprogram specification>;
  3105.    --   <purpose>
  3106.  
  3107.     with <subprogram specification> is <>;
  3108.    --   <purpose>
  3109.  
  3110.     with <subprogram specification> is <default name>;
  3111.    --   <purpose>
  3112.  
  3113. The <subprogram specification> should be formatted as for a subprogram
  3114. declaration (see paragraph 5.6.3.3).  Note, however, that the only
  3115. documentation generally needed on formal subprograms is the "Purpose."
  3116.  
  3117.     c.  A generic declaration should be preceded by the appropriate unit
  3118. header block (see paragraphs 5.6.6.2 and 5.7.5.2).
  3119.  
  3120. 5.12.6.2  Formatting of generic instantiations.
  3121.  
  3122.     a.  Generic instantiations should have one of the following formats:
  3123.  
  3124.     <unit header> is
  3125.       new <generic name> (<generic argument>, <generic argument>);
  3126.  
  3127.    --  <documentary comments>
  3128.     <unit header> is
  3129.       new <generic name>
  3130.         ( <generic parameter> => <generic argument>,
  3131.           <generic parameter> => <generic argument>);
  3132.  
  3133.         <documentary comments>
  3134.  
  3135. NOTE:  In the second form the arrows ("=>") should be kept aligned.  Also, the
  3136. <documentary comments> should not duplicate information presented in the
  3137. generic specification.  A referral back to the original comments should be a
  3138. good beginning.
  3139.  
  3140.     b.  Generic instantiations should have the same kind of header comment
  3141. block as for a specification of the appropriate kind of unit (paragraphs
  3142. 5.6.6.2 and 5.7.5.2).
  3143.  
  3144. 5.12.7  Examples for generic units.  See also examples 5.7.6.2 and 5.7.6.3.
  3145.  
  3146. 5.12.7.1  Example 12X1.
  3147.  
  3148.        --  ........................
  3149.        --  .                      .
  3150.        --  .  Shellsort_Generic   .     SPEC
  3151.        --  .                      .
  3152.        --  ........................
  3153.  
  3154.     generic
  3155.       type ITEM is private;    -- The type of items sorted
  3156.       type LIST_TYP is         -- The type of the item list
  3157.         array (INTEGER range <>) of ITEM;
  3158.  
  3159.       with function "<"
  3160.         ( Left  : ITEM;
  3161.           Right : ITEM )
  3162.         return BOOLEAN is <>;
  3163.  
  3164.   --  Purpose
  3165.   --  This function defines the ordering used when the
  3166.   --  items are sorted.
  3167.  
  3168.     procedure Shellsort_Generic
  3169.       ( List : in out LIST_TYP ;  -- This list will be sorted in place.
  3170.         N    : in     NATURAL );  -- The number of items in the list.
  3171.  
  3172.   --  Purpose
  3173.   --  This procedure sorts the items in List using a Shell
  3174.   --  sort algorithm designed for parallel processing.
  3175.   --
  3176.   --  Exceptions (none)
  3177.   --
  3178.   --  Notes
  3179.   --  (This is a generic declaration for the procedure
  3180.   --  body five in example 9X3.)
  3181.   --
  3182.   --  Modifications
  3183.   --  9/5/86    A. Shell        Initial version
  3184.  
  3185. 5.12.7.2  Example 12X2.
  3186.  
  3187.        --  .....................
  3188.        --  .                   .
  3189.        --  .    Name_Sort      .   SPEC
  3190.        --  .                   .
  3191.        --  .....................
  3192.  
  3193.     procedure Name_Sort is
  3194.       new Shellsort_Generic
  3195.         ( ITEM       => NAME,
  3196.           LIST_TYP   => NAME_LIST );
  3197.  
  3198. 5.12.7.3  Example 12X3.
  3199.  
  3200.        --  *************************
  3201.        --  *                       *
  3202.        --  *                       *
  3203.        --  *    Unit_Statistics    *    SPEC
  3204.        --  *                       *
  3205.        --  *************************
  3206.  
  3207.     with Text_IO;
  3208.     generic
  3209.  
  3210.       Unit_Name                 -- Name of the unit for which
  3211.         : STRING;               -- statistics are to be kept.
  3212.  
  3213.       type ELEMENT_TYP is       -- Enumeration type of the elements
  3214.         (<>);                   -- to be counted.
  3215.  
  3216.     package Unit_Statistics is
  3217.    --  Purpose
  3218.    --  This package provides operations to keep counts for the
  3219.    --  various elements of a program unit.  These counts can be
  3220.    --  incremented or printed out in a report.
  3221.    --
  3222.    --  Initialization Exceptions (none)
  3223.    --
  3224.    -- Notes
  3225.    --
  3226.    --  This package is based on the generic package "Task_Statistics"
  3227.    --  written by Dan Roy.
  3228.    --
  3229.    --  Modifications
  3230.    -- 8/18/86 Ed Seidewitz Initial version
  3231.  
  3232.        -- ............................
  3233.        -- .                          .
  3234.        -- .    Number_Of_Lines       .   SPEC
  3235.        -- .                          .
  3236.        -- ............................
  3237.  
  3238.   function Number_Of_Lines
  3239.     return POSITIVE;
  3240.  
  3241.   --  Purpose
  3242.   --  This function returns the number of lines printed by
  3243.   --  procedure Report since the last call to Number_Of_Lines.
  3244.   --
  3245.   --  Exceptions (none)
  3246.   --
  3247.   --  Notes (none)
  3248.  
  3249.        --  ...........................
  3250.        --  .                         .
  3251.        --  .        Count_of         .    SPEC
  3252.        --  .                         .
  3253.        --  ...........................
  3254.  
  3255.   function Count_Of
  3256.     ( Element : ELEMENT_TYP ) return NATURAL;
  3257.  
  3258.   --  Purpose
  3259.   --  This function returns the current count for the specified
  3260.   --  element.
  3261.   --
  3262.   --  Exceptions (none)
  3263.   --
  3264.   --  Notes (none)
  3265.  
  3266.        --  ...................
  3267.        --  .                 .
  3268.        --  .   Increment     .   SPEC
  3269.        --  .                 .
  3270.        --  ...................
  3271.  
  3272.  procedure Increment
  3273.    ( Element     : in ELEMENT_TYP;
  3274.      By_Amount   : in INTEGER       := 1 );
  3275.  
  3276.   --  Purpose
  3277.   --  This procedure increments the count for the specified
  3278.   --  element by a certain amount.  By default, this amount
  3279.   --  is one.
  3280.   --
  3281.   --  Exceptions (none)
  3282.   --
  3283.   --  Notes (none)
  3284.  
  3285.        --  ....................
  3286.        --  .                  .
  3287.        --  .     Report       .     SPEC
  3288.        --  .                  .
  3289.        --  ....................
  3290.  
  3291.  procedure Report
  3292.    ( Report File  : in  Text_IO.FILE_TYP );
  3293.  
  3294.   --  Purpose
  3295.   --  This procedure prints a report of all statistics for
  3296.   --  this unit to the specified text file.
  3297.   --
  3298.   --  Exceptions (none)
  3299.   --
  3300.   --  Notes (none)
  3301.  
  3302. end Unit_Statistics
  3303.  
  3304. 5.12.7.4  Example 12X4.
  3305.  
  3306.        --  ***********************************
  3307.        --  *                                 *
  3308.        --  *  Telemetry_Reader_Statistics    *     SPEC
  3309.        --  *                                 *
  3310.        --  ***********************************
  3311.  
  3312.     package Telemetry_Reader Statistics is
  3313.       new Unit_Statistics
  3314.         ( Unit_Name       => "Telemetry_Reader",
  3315.           ELEMENT_TYP     => READER_ELEMENTS );
  3316.  
  3317.    --  Purpose
  3318.    --  This package collects statistics on elements of the
  3319.    --  Telemetry_Reader.
  3320.    --
  3321.    --  Initialization Exceptions (none)
  3322.    --  Notes (none)
  3323.  
  3324. 5.13  Representation clauses and implementation-dependent features.  Any
  3325. library units using representation clauses and implementation-dependent
  3326. features should explicitly document their use.  One of the attractions of
  3327. Ada is its code reusability.  If only machine independent interfaces are
  3328. presented, while representation clauses and implementation features are
  3329. hidden, those wishing to make use of the code may find unexplainable errors
  3330. arising.
  3331.  
  3332.  
  3333. 5.13.1  Encapsulation.  Representation clauses and implementation dependent
  3334. features should, if possible, be hidden inside packages which present
  3335. implementation independent interfaces to users.
  3336.  
  3337. 5.13.2  Use of representation clauses and implementation-dependent features.
  3338.  
  3339.     a.  Machine dependent and low-level Ada features should not be used except
  3340. when absolutely necessary.
  3341.  
  3342.     b.  Representation clauses and implementation-dependent features should
  3343. only be used for one of the following:
  3344.  
  3345.         (1) To increase efficiency (when absolutely necessary).
  3346.         (2) For interrupt handling.
  3347.         (3) For interfacing to hardware, foreign code or foreign data.
  3348.         (4) To specify task storage size. Further, address clauses should be
  3349.         used with entries only to associate them with hardware interrupts.
  3350.  
  3351.     c.  Representation clauses should not be used to change the meaning of a
  3352. program.
  3353.  
  3354. 5.13.3  Interrupts.  Interrupt routines should be kept as short as possible.
  3355.  
  3356. 5.13.4  Formatting of representation clauses.  Representation clauses should
  3357. be placed near the objects they affect.  An exception may be to separate the
  3358. machine-independent from the machine-dependent representations.
  3359.  
  3360. 5.14  lnput-output.
  3361.  
  3362.  
  3363. 5.14.1  Encapsulation of I/O.
  3364.  
  3365.     a.  Use of the LOW_LEVEL_IO procedures should always be encapsulated in
  3366. packages or tasks.
  3367.  
  3368.     b.  Use of the LOW_LEVEL_IO procedures should generally be encapsulated in
  3369. task objects associated with each item of controlled equipment.
  3370.  
  3371.     c.  File management and textual input-output software should generally be
  3372. encapsulated in specialized packages with simple interfaces.
  3373.  
  3374. This should include file interface code, textual formatting code and user
  3375. inter-face code.  User interface encapsulation can be especially useful when a
  3376. system must accommodate increasing levels of user interface sophistication or
  3377. changing user needs over its lifetime.  In these cases it is crucial that
  3378. details of the implementation of the user interface be hidden so that changes
  3379. can be made to it without affecting the rest of the system.
  3380.  
  3381. NOTE:  An argument can be made to encapsulate all I/O, to include the use
  3382. Text_IO and Direct_IO, because most Ada I/O has machine dependencies.
  3383.  
  3384. 5.14.2  Text formatting.  Line and page formatting should be done using the
  3385. New_Line and New_Page subprograms, rather than explicitly writing end-of-line
  3386. or end-of-page characters.
  3387.  
  3388. 5.14.3  Low-level input-output.  Use of package Low_Level-IO should be
  3389. avoided unless absolutely necessary.
  3390.  
  3391. 5.14.4  Form parameter.  Use of the Form parameter of the Open and Create
  3392. procedures should generally be avoided.
  3393.  
  3394. The "Form" parameter on the file Open and Create procedures specifies system
  3395. dependent file characteristics.  This can reduce both readability and
  3396. portability, and so should only be used if absolutely necessary.
  3397.  
  3398. 5.14.5  Examples for input-output.  See also examples 5.5.9.3, 5.5.9.4 and
  3399. 5.7.6.3.
  3400.  
  3401. 5.14.5.1  Example 14X1.
  3402.  
  3403.        --  ....................
  3404.        --  .                  .
  3405.        --  .      Report      .   SUBUNIT
  3406.        --  .                  .
  3407.        --  ....................
  3408.  
  3409.     separate (Unit_Statistics)
  3410.     procedure Report
  3411.       ( Report_File : in  Text_IO.FILE_TYP ) is
  3412.  
  3413.    --  Notes
  3414.    --  This example is based on Task_Statistics.Report
  3415.    --  by Dan Roy.
  3416.    --
  3417.    --  Modifications
  3418.    --  8/18/86    Ed Seidewitz   Initial version.
  3419.  
  3420.       Unit_Name_Column
  3421.         : constant := 10;
  3422.  
  3423.       Value_Column
  3424.         : constant := 40;
  3425.  
  3426.       use Text_IO;         -- For output operations.
  3427.  
  3428.     begin    -- Report
  3429.  
  3430.       -- Print header
  3431.       New_Line (Report File);
  3432.       Set_Col (Report. File, To => Unit_Name_Column);
  3433.       Put_line (Report_File,
  3434.           "Statistics for " & STRING(Unit_Name)); New Line (Report_File);
  3435.       Number_Lines_Printed := Number_Lines_Printed . 2;
  3436.  
  3437.       -- Print "element name element value" for all elements
  3438.       Print_All:
  3439.       for Element in Statistics Array'range loop
  3440.         Put (Report_File, ELEMENT_TYP'image (Element));
  3441.         Set Col (Report_File, To => Value_Column);
  3442.         Put Line (Report_File, INTEGER'image (Statistics_Array(Element)));
  3443.         Number_Lines_Printed := Number_Lines_Printed + 1;
  3444.       end loop Print_All;
  3445.  
  3446.     end Report;
  3447.  
  3448. 5.14.5.2  Example 14X2.
  3449.  
  3450.        --  ....................
  3451.        --  .                  .
  3452.        --  .      Read        .   SUBUNIT
  3453.        --  .                  .
  3454.        --  ....................
  3455.  
  3456.     separate (Disk)
  3457.     procedure Read
  3458.       ( Disk_File : in out FILE_TYP;
  3459.         Data      : out    SPECIFIC_DATA_TYP ) is
  3460.  
  3461.    --  Notes
  3462.    --  (This is the body of procedure Read in example 7X3)
  3463.  
  3464.    --  Modifications
  3465.    --  9/10/86     Ada User's Group      Initial version
  3466.  
  3467.     begin   -- Read
  3468.  
  3469.       if not Disk_IO.Is_Open(Disk_File.File) then
  3470.         Open_File(Disk_File);
  3471.       end if;
  3472.  
  3473.       Disk_IO.Read
  3474.         ( File => Disk_File.File,
  3475.           Item => Data );
  3476.  
  3477.     exception
  3478.  
  3479.       when Disk_IO.End Error =>
  3480.         Disk_IO.Close (Disk_File.File);
  3481.         raise End_Of_File;
  3482.       when Disk_IO.Name Error  Disk_IO.Use_Error =>
  3483.         raise Open_Error;
  3484.       when Disk_IO.Mode_Error =>
  3485.         raise Mode_Error;
  3486.  
  3487.     end Read;
  3488.